trouble with imdecode: always returns none. Why?

asked 2019-12-15 08:02:14 -0600

I wrote streaming via UDP in python applying compression with send and rec as below

send.py

        import socket
        import numpy as np
        import cv2 as cv
        import sys
        addr = ("127.0.0.1", 65534)
        buf = 512
        width = 640
        height = 480
        cap = cv.VideoCapture('test.mp4')
        cap.set(3, width)
        cap.set(4, height)
            code = 'start'
            code = ('start' + (buf - len(code)) * 'a').encode('utf-8')
            np.set_printoptions(threshold=sys.maxsize)
            lenght=bytearray(3)
            encode_param = [int(cv.IMWRITE_JPEG_QUALITY), 90]
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            frame=np.array([[[255, 255, 216],  # i use a small array instead of frame from test video to debug
              [255, 255, 215],
              [255, 255, 210],
              [255, 255, 210],
              [255, 255 ,209],
              [255, 255, 209],
              [255, 255 ,213],
              [255, 255, 213],
              [255, 255, 208],
              [255, 255 ,208]]])
            print('original')
            print(frame) 
            result, frame = cv.imencode('.jpg', frame, encode_param)
            print('frame after encode')
            print(frame)
            print('length')
            print(len(frame))             
            frame2 = cv.imdecode(frame, cv.IMREAD_COLOR)#
            print('frame2 test decode before sending')
            print(frame2)
            lenght[0]=len(frame)//(256**2)
            lenght[1]=((len(frame)%(256**2))//256)
            lenght[2]=((len(frame)%(256**2))%256)
            data=lenght+bytearray(frame) 
            for i in range(0, len(data), buf):
             s.sendto(data[i:i+buf], addr)
            cv.imshow('send', frame2)

rec.py

import socket
    import numpy as np
    import cv2 as cv
    import sys
    np.set_printoptions(threshold=sys.maxsize)
    addr = ("127.0.0.1", 65534)
    buf = 512
        width = 640
        height = 480
        code = b'start'
        num_of_chunks = width * height * 3 / buf
        data = b""
        if __name__ == '__main__':
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.bind(addr)
            while True:
                while len(data)<3:
                 data+= s.recvfrom(buf)[0]

                length=data[0]*(256**2)+data[1]*256+data[2]
                data = data[3:]
                #print("msg_size: {}".format(length))
                while len(data) < length:
                    data+= s.recvfrom(buf)[0]

                frame_data = data[:length]
                data = data[length:]  
                frame=np.zeros((len(frame_data),1),dtype=int)
                for j in range(len(frame_data)):
                 frame[j]=frame_data[j]
                print('frame collected before decode')
                print(frame)
                print('length')        
                print(len(frame))
                frame2 = cv.imdecode(frame, cv.IMREAD_COLOR)



                cv.imshow('recv', frame2)
                if cv.waitKey(1) & 0xFF == ord('q'):
                    break

            s.close()
            cv.destroyAllWindows()

Now is the problem, the rec.py gets frame2 after decode is None. I thought my transmission is problematic so data is lost but i check "frame collected before decode"in rec.py and "'frame after encode" printed in send.py. they are identical, it means the data sent and collected properly. any opinion why decode gives None in my case?

edit retag flag offensive close merge delete

Comments

1

Can you reproduce problem without socket?

LBerger gravatar imageLBerger ( 2019-12-15 10:12:56 -0600 )edit

I still have no idea to do that. Would be nice to learn from you. But i printed frame after encode at "send" side and frame before decode at "rec" side and they are identical. I tried using that array as input of decode in IDE and it works. I actually tested decode with that array before sending in my code above and it works

abcdcadb gravatar imageabcdcadb ( 2019-12-15 10:22:03 -0600 )edit

On recv.py side:

nparr = numpy.fromstring(data, numpy.uint8)
frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

Use sendall instead of send.

supra56 gravatar imagesupra56 ( 2019-12-15 10:22:46 -0600 )edit

Hi supra, I tried your suggestion with numpy.fromstring and decode's result still is None. Also i am using Udp thus sendall is not available (it aks for an established connection that only can be done with TCP)

abcdcadb gravatar imageabcdcadb ( 2019-12-15 11:04:20 -0600 )edit

your networking code looks flawed.

udp packets may not be larger than 64k, packets may get fractured, your client code does not respect that

please start with TCP instead

berak gravatar imageberak ( 2019-12-16 03:27:49 -0600 )edit