2

I am trying to read an opencv image in a python socket that is sent from c++.

I am able to read the image into another c++ program or VB program and build an image but with python I don't understand what's happening.

The sending code where I send the mat.data:

char *start_s = "<S><size>43434234<cols>64<rows>64<SE>";//plus I send the image size, cols, rows, which varies, not like the static char string shown
char *end_e = "<E>";
cv::Mat image_send = some_mat;
iResult = send( ConnectSocket, start_s, (int)strlen(start_s), 0 );
iResult = send( ConnectSocket, (const char *) image_send.data, i_buffer_size, 0 );
iResult = send( ConnectSocket, end_e, (int)strlen(end_e), 0 );

This is what I have tried with the python, but haven't had any success yet. The image_cols and Image_rows are filtered from the socket, not shown here, and only the image_mat.data from the c++ mat is in the socket that I am trying to put into the image:

data = conn.recv(4757560)
        if(i_Read_Image == 2) & (image_cols != 0) & (image_rows != 0):
            print ("Entering")
            #print(data)
            data2 = np.fromstring(data, dtype='uint8')
            img_np = cv2.imdecode(data2,cv2.IMREAD_COLOR )
            cv2.imshow('image',img_np)
            cv2.waitKey(0)

            #Also tried this
            #img = Image.new('RGB', (image_cols, image_rows))
            #img.putdata(data)

        #img5 = np.reshape(data2,(image_rows,image_cols))
        i_Read_Image = 0
jester
  • 238
  • 5
  • 13
  • What do you mean by "haven't had any success yet"? What happens? I assume this is just trial code trying to get it to work, but in reality you don't want to hard code the number of bytes to `recv`. You've already read `image_cols` and `image_rows` so you can compute the number of additional bytes needed from the socket. – MFisherKDX Dec 22 '17 at 05:46
  • The code above, I get an error that the size needs to be greater than 0. if I print(data2), everything looks fine:[154 207 255 ..., 51 56 79] but line with img_np throws error : error: (-215) size.width>0 && size.height>0 in function cv::imshow – jester Dec 22 '17 at 05:50
  • Did you send the raw pixel data on the socket? I think all you need to do is reshape `data` into the correctly sized 2D array. I don't quite understand why you are calling `fromstring` or `imdecode`. – MFisherKDX Dec 22 '17 at 06:03
  • Does this help: https://stackoverflow.com/questions/47881656/how-to-receive-video-through-socket-opencv-2-4-13/47897458#47897458 – Kinght 金 Dec 22 '17 at 06:09
  • 1
    Something like `img_np = data.reshape((image_rows, image_cols, image_channels))` – MFisherKDX Dec 22 '17 at 06:10
  • I tried img_np =data.reshape((image_rows, image_cols, image_channels)) as well as doing this first data2 = np.fromstring(data, dtype='uint8') and using data2 but I still get errors: AttributeError: 'bytes' object has no attribute 'reshape' – jester Dec 22 '17 at 06:18
  • I do send the raw pixel data only: (const char *) image_send.data, – jester Dec 22 '17 at 06:20
  • My apologies. `recv` returns a string. So you need the `fromstring` first on `data` then then reshape on `data2` – MFisherKDX Dec 22 '17 at 06:25
  • Thank you @MFisherKDX for all the help, I used data2. one thing I was missing originally was specifying the number of image channels as you showed above. – jester Dec 22 '17 at 06:36

1 Answers1

1

With the help of the comments I was able to get a working answer. The original image is in a single array RGB, this needs to be reshaped and placed into a 'RGB' image, it can be done in one line:

img = Image.fromarray(data2.reshape(image_rows,image_cols,3), 'RGB')

and when reading an opencv data array from a socket: this works:

data = conn.recv(567667)
if(i_Read_Image == 2) & (image_cols != 0) & (image_rows != 0):
    data2 = np.fromstring(data, dtype='uint8')
    img = Image.fromarray(data2.reshape(image_rows,image_cols,3), 'RGB')
    img.show()
jester
  • 238
  • 5
  • 13