pythonnumpyopencvbitmapwxpython

"ValueError: Invalid data buffer size." in wx.Bitmap.FromBuffer after converting Nmpy image from BGR to RBG


I am converting a numpy image from BGR to RBG format and this image is being converted into wx.Bitmap image, but while doing so i am getting "ValueError: Invalid data buffer size." for BITMAP image. And without BGR to RBG conversion BITMAP image is being yielded properly.

code with the error:

class Video:
    def __init__(self):
        # self._filename = file_name
        self._frame_number = -1
        self._cap = cv2.VideoCapture('Path/t/o/Video')  ###self._filename
        self._frameCount = int(self._cap.get(cv2.CAP_PROP_FRAME_COUNT))
        self._frameWidth = int(self._cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        self._frameHeight = int(self._cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        self._frame_count = 0
        self._frame_grabbed = True
        self.img = np.array((self._frameHeight, self._frameWidth, 3), np.dtype('uint8'))

    def iter_frames(self): # Generator to return Numpy and BitMap Image 
        while self._frame_count < self._frameCount and self._frame_grabbed:
            self._frame_count += 1
            self._frame_grabbed, self.img = self._cap.read()
            print(type(self.img))
            #self.img.reshape(self._frameHeight,self._frameWidth, 3)
            self.img = self.img[..., ::-1]  # To convert BGR to RGB
            yield self.img, wx.Bitmap.FromBuffer(self._frameWidth, self._frameHeight, self.img)

v=Video()
print(next(iter_frames()))

Error Encountered:

  File "C:/Users/qpjg1605/Documents/Python_proj/Auptimo/Video_file.py", line 46, in <module>
    print(next(v.iter_frames()))
  File "C:/Users/qpjg1605/Documents/Python_proj/Auptimo/Video_file.py", line 30, in iter_frames
    yield self.img, wx.Bitmap.FromBuffer(self._frameWidth, self._frameHeight, self.img)
ValueError: Invalid data buffer size.

But when I am using the code for array of numpy arrays(self._buf[]) its working all fine"

Code for the same:

class Video:
    def __init__(self):
        # self._filename = file_name
        self._frame_number = -1
        self._cap = cv2.VideoCapture('Path\to\Video')  ###self._filename
        self._frameCount = int(self._cap.get(cv2.CAP_PROP_FRAME_COUNT))
        self._frameWidth = int(self._cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        self._frameHeight = int(self._cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        self._buf = np.empty((self._frameCount, self._frameHeight, self._frameWidth, 3),np.dtype('uint8'))  # Empy numpy array of the shape and dtype(pixel from 0 to 255)   

        self._frame_count = 0
        self._frame_grabbed = True
        print("here")
        while self._frame_count < self._frameCount and self._frame_grabbed:
            self._frame_grabbed, self._buf[self._frame_count] = self._cap.read()
            self._buf[self._frame_count] = self._buf[self._frame_count][..., ::-1]## Converting BGR to RBG(last dimension)
            #self._buf[self._frame_count] = imutils.resize(self._buf[self._frame_count], 640, 360)
            self._frame_count += 1


    def iter_frames(self):
        while self._frame_number < self._frameCount:
            self._frame_number = self._frame_number + 1
            # yield int(self._frame_number)
            # cur_bmp = wx.Bitmap.FromBuffer(self.get_org_frame_width(), self.get_org_frame_height(), )
            print(self._frame_number)
            yield self._buf[self._frame_number], wx.Bitmap.FromBuffer(self.get_org_frame_width(),
                                                                      self.get_org_frame_height(),
                                                                      self._buf[self._frame_number])

Solution

  • Figured it out the Bitmap conversion issue:

     def iter_frames(self):   # Frame Generator to yield next frame
        while self._frame_count < self._frameCount and self._frame_grabbed:
            self._frame_count += 1
            self._frame_grabbed, self.img = self._cap.read()
            self.img = cv2.cvtColor(self.img,cv2.COLOR_BGR2RGB)
            yield self.img, wx.Bitmap.FromBuffer(640, 360, cv2.resize(self.img, (640, 360)))
    

    `