I have a rectangle area on a pygame surface. I want to convert that area into opencv image object (without saving into a file) for further image processing on that rectangle area only. How can I do that?
selected_area = mysurface.subsurface((x,y,w,h))
img_array=numpy.array(pygame.surfarray.array2d(selected_area))
#image_object = ..... ?
gray = cv2.cvtColor(image_object, cv2.COLOR_BGR2GRAY)
cv2.imshow("test",gray)
>Solution :
Actually, a cv2 image is just a three-dimensional numpy array. the 1st dimension is the height, the 2nd the width and the 3rd the number of channels in the order blue, green, red.
Use pygame.surfarray.pixels3d to reference pixels into a 3d array:
img_array = numpy.array(pygame.surfarray.pixels3d(selected_area))
Unfortunately, this array is flat and the pixels are stored in row mayor order. The color channels are in the order red, green, blue. So you need to reformat this array. reshape the and transpose the array:
image_object = numpy.rollaxis(img_array.reshape((w, h, 3)), 1)
Finally swap the red and blue color channel:
image_object[:, :, [0, 2]] = image_object[:, :, [2, 0]]
Convert function:
def pygameSurfaceToCv2Image(mysurface, x, y, w, h):
selected_area = mysurface.subsurface((x, y, w, h))
img_array = numpy.array(pygame.surfarray.pixels3d(selected_area))
image_object = numpy.rollaxis(img_array.reshape((w, h, 3)), 1)
image_object[:, :, [0, 2]] = image_object[:, :, [2, 0]]
return image_object
Minimal example:
import pygame
import cv2, numpy
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
def pygameSurfaceToCv2Image(mysurface, x, y, w, h):
selected_area = mysurface.subsurface((x, y, w, h))
img_array = numpy.array(pygame.surfarray.pixels3d(selected_area))
image_object = numpy.transpose(img_array.reshape((w, h, 3)), (1, 0, 2))
image_object[:, :, [0, 2]] = image_object[:, :, [2, 0]]
return image_object
apple_surf = pygame.image.load("Apple1.bmp")
image_object = pygameSurfaceToCv2Image(apple_surf, 20, 20, 200, 120)
gray = cv2.cvtColor(image_object, cv2.COLOR_BGR2GRAY)
cv2.imshow("apple subsurface", image_object)
cv2.imshow("gray apple subsurface", gray)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(0)
window.blit(image, image.get_rect(center = window.get_rect().center))
pygame.display.flip()
clock.tick(60)
pygame.quit()
exit()
