img = np.float32(img)
img = img[0::2, :] + img[1::2, :]
img = img[:, 0::2] + img[:, 1::2]
img = np.uint8(img / 4)
img = np.uint8(
(np.float32(img[0::2, 0::2]) + img[0::2, 1::2] + img[1::2, 0::2] + img[1::2, 1::2]) / 4
)
kernel = np.ones((2, 2), dtype=np.float32) / 4
img = cv2.filter2D(img, cv2.CV_8U, kernel, anchor=(0, 0))[::2, ::2]
img = np.lib.stride_tricks.as_strided(
img, (*np.array(img.shape[:2]) // 2, 4, 3), (*np.array(img.strides[:2]) * 2, *img.strides[1:])
).mean(axis=-2).astype(np.uint8)