Serial and JPEG decoding

  1. Where did you get the camera module(s)?
    ArduCam directly

  2. Model number of the product(s)?
    OV5642_MINI_5MP

  3. What hardware/platform were you working on?
    Arduino Uno / Pycharm

  4. Instructions you have followed. (link/manual/etc.)
    ArduCam HowTo
    ArduCam GitHub

I took these and modified the OV5642_MINI_5MP_PLUS example to get byte streams into pycharm.

I also opened the host_app in the Github and while it works, it doesn’t help me transfer that to decoding into JPEG formats, etc. Since it’s all .exe / .dll files.

  1. Problems you were having?
    I’m trying to decode the bytes (remove b’ /n’ from every line) and decode the file so I can open it in JPEG format on my computer

  2. The dmesg log from your hardware?
    I don’t know what this is.

  3. Troubleshooting attempts you’ve made?
    For decode byte stream, I have tried to .decode(‘utf-8’) and .decode('utf-16) and I get a generic decoding error somehow it printed chinese too:
    For utf-8:

Other error occurred: ‘utf-8’ codec can’t decode byte 0xff in position 0: invalid start byte

For utf-16:

牁畤䅃⁍瑓牡ⅴ਍
Other error occurred: ‘utf-16-le’ codec can’t decode byte 0x0a in position 18: truncated data

For opening the JPEG, I’m trying to understand encoding and formats but all I’m getting when I trim the mentioned encoding headers is a message about file type not being supported.

  1. What help do you need?
    What is the decode type I should use to decode the hex byte format? (See file)
    How can I convert the hex stream to a JPEG file which I can save / open on the computer? I’d like to use openCV/pycharm if possible but am finding it hard to find the right documentation.

How do I attach a .txt file? Until then, here are the first and last 2 lines of the data stream I am getting.

b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00\x00\x00\x00\x00\x00\xff\xdb\x00C\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\t\t\x08\n'
b'\x0c\x14\r\x0c\x0b\x0b\x0c\x19\x12\x13\x0f\x14\x1d\x1a\x1f\x1e\x1d\x1a\x1c\x1c $.\' ",#\x1c\x1c(7),01444\x1f\'9=82<.342\xff\xdb\x00C\x01\t\t\t\x0c\x0b\x0c\x18\r\r\x182!\x1c!22222222222222222222222222222222222222222222222222\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n'
b'h\x04u\x14\x8b\x93\xf4\xa0C\xfe\x95&\xde1Lc\xe1o*\x9a\xee7v\xa4\x04OU\x1f\x199SH\x06\x14\xe7\x8e\x94d\xb5;\x08v6\xf7\xfc)\xa5\x93\x18\xff\x00&\xa9\x0c\x01\xfe\xe8\xa4\x04\x97\xc9\xa4\x05\x8d\xbc\x03\x8ei\xbf\xad0\x0f\xe2\xe3\x8a>\x87\x8fJ\x00]\x80\x91\xf2\xd3\x87Z\x00V\x1f/\x155\xbbq\x9e\xb4\xc0\xb1\xe6q\xcd5\x9b\xb5\x00<I\xbb\x1cS\xd1\xf2q@\x12\x8av\xef\x9b\x1f\xca\x80&\x14\xf0\xc2\x98\x12-?\xb5\x00.s\x83Rg\x83@\x0b\xda\x9c\xb4\x00\xfc\xf3\x8aG\xc6\x06h\x03\x86\xb7\xe2B\xb9\xcey\xc1\xa9x\x07\xa7Z\xe5Fc\xa1\xe3\x03\xf9U\xcf3\x8e\x7f:\xd1l1\xbe\xe0\xe4\xd3\x0f\xe1\x93\xda\x9bz\x0c\x8d\xc6p\n'
b'\xe6\x9b\xfc\x1c\x81P\x03N\x17>\xb4\xe1\x948\xdcI4\x00\x06\xcb\x9e8\xa5\x8cFWp\xc54\x04\x84ry\xe9Q2\xf5\xc0\xa2C\x19\x80ri\xdb\xb8\xa9\xb8\x08I$\x8f\xe5OA\xc6(L\t3\x81LQ\xc9\'\xa5P\x04\x91\xe4\xee\x1d\xbbS\x15y\xe9F\x80<.:~\xb4\xed\xbf(\x14\x00\x1a6\xf6\xa0b\x0e\r)\xfb\xd4\x00d\x8e\xbc\xd4[\x8e\xeaW\xb0\t\xbd\xbc\xde\xb4\xe6\xeeG\x06\x9a\x01\xbb\xb6u=h\xe89\xa0\x03\xd3\x9aS\xc7LP\x80\x83f\t%\xb9\xa8\xcc\xb8~i\x88qq\xb7\x1d\xe9\xa2`~S\xf8\xd5_Q\x12,\xbb\xc7\x14\xed\xfbZ\x95\xc69\xa5\x1d\xe8\xc9\xf7\xc5\x03\x1b\xe6\x9eA\xe9R,\xad\xd3\x18\xa0\x07y\xbe\xa6\x93~x?\x8d4"P\x9b\xd75Y\xd0\x9fjC\x19\xb3m3#\'>\x95W\x10\x83<\xe0\xfd)\x87\xe4$\xb5\x00"\x86\xdav\x1d\xde\xbd\xe9\xcb\xc1\xfa\xd0\x04\xb9<|\xbd\xe9\x1b\x80}\xbaS\x18\xa7\xe69\xa7\x0f\x90\xfaf\x80\x1c\xa4\xfag\xde\x94}\xeex\xa6\x02\xabo;j\xc2|\xa3\x8a@;\xaf4\xe5\x04w\xaa\x01v\xa8\xa9\x05 \x1f\xces\x8a\x91qL\t\x17\xa7\x1d*\\\xe2\x80\x055"\xe34\x80vs\xf5\xa93\x8f\\\xd3\x01\xddG\xbdH\x1b\x8a\x00w\x14\x93v\xa0\x0e\x0e\xdd\xc6z\xeecV\x1bo\x0cJW"\x8e\x86D\x96\xce\xa1\xb1\xfa\xd4\xb29\xc0\xfe\xa6\xae;hX\xc0\xfby,)\xcd*\xb2u\xfc\rP\r\xdc\x8d\xfcC\xf3\xa6\xb1\xe4f\x90\x08]s\xc1\x1e\xf4\xa3nK\x02:z\xd4\xdb\xb0\x061\x9cu\xa5$\x01\xcdW\x98\xc3p\xf5\xfdh;I\xfb\xdf\xadM\xae\x023s\xd4SI\x18\xeb\xd3\xd2\xa5\x8c\x95x\xe7?J7\x12{U\x00/_\xbdR1\x04})\xa0#\xc8?\xc5\xf5\xa9F\xcfjh\x06\x9d\xa4\xd2n\xcfzZ\x80u\xe6\x8es\xce(\xb0\x01\xff\x00e\xb9\xa4?ZV\x013\x81\xd6\xa2\x0e3\xe9T\x01\x94\xa5\'\xde\x80\x18\x1f?\x85<\x1ez\x8cP\x80k\x1e8jn\xee\x9c\xd2\x02&ns\x9a\x8d\x9b\x04t\xe9\xcdQ#3\xde\x83\xc9\xce\xef\xc4\x1a\x00x\x01@\xf4\xf7\xa5\xf3:q\xda\x9d\x80]\xeb\x8f\xfe\xbdH\xaeO\xcaq\x8fZ\x06&\xecm\x00\xfe4\xed\xdfJv\xb0\x0b\x91\xb8r=\xe9\xad&;\xd3\x01\xf1\\v\xdd\x9a\x9d\xf6\x9eA\x19\xa2\xc0@\xdc\x1e\xbc\xfaSI\x0b\xdcR\x01\xa7\x00\xaf5\x19\xc1\xcf\xcdL\x06#l^H\xf7\xa7n\xdf\xc0q\xc5\x08c\xbc\xc5\xc9\xc9\xf7\xa9\x06\xcf\xeff\x81\x0b\xfcg\x9e\x0fj\x01^\x9f\xd6\x81\x8c\xf3\x030\xf9\xb9\xf5\xa7\x86\x19\xceFM0%,=i\xfb\x94\x0e\xbc\xd0\x03\xb3\x9e3Ro\\v\xf6\xa0\x05V\xe3\xf8ja"\x81\xd6\x98\x0f\xde\x0fqO]\x98\xceh\x01\xc0\xa8^\r;\xcd\xa0\t\x14\xe3\xa6\x0588\xfe\xf09\xa6\x04\xb9\x1e\xb4\xe0\xc3\xd4P\x03\xc3/L\xd3\xc3\x8a\x00^\x0f|RK\x82\x07\xcd@\x1f\xff\xd9\n'

Ok I figured out that I can put the response into hex literal form with the below line in pycharm… but what do I do with it after that?
data = bytes.hex(returnedBytes)

I finally got it after much iteration and learning about the serial commands and byte / char structuring. I’m still not sure why there is no documentation for how to convert a data stream on the PC end. And while I know this works, it seems like it is still about 3 times slower than the host_app takes.

import serial
import cv2 as cv
import numpy as np

arduino = serial.Serial(port='COM3', baudrate=500000)
settings = arduino.get_settings()

try:
    # send_trigger is the last text arduino sends while setting up. This means it's buffer will be empty.
    send_trigger = b'OV5642 detected.\r\n'
    temp = arduino.read_until(send_trigger)

    print("Send Acq Request")

    # Send /x10 (hex 10 = 16 dec) to trigger an image acquisition
    arduino.write(bytes.fromhex("10"))

    print("reading")

    # start_check is the first bytes sent for the picture in JPEG format.
   # Read and clear everything sent leading up to that.
    start_check = b'\xff\xd8'
    temp = arduino.read_until(start_check)

    # end_check are the last bytes sent for the picture.
    # since start_check will be read (and cleared from the buffer) you need to add it to the start of the data stream.
    end_check = b'\xff\xd9'
    data = start_check + arduino.read_until(end_check)

    # decode the data into a byte array, then an numpy array object
    image = np.asarray(bytearray(data), dtype="uint8")
    # Send the numpy array object to an opencv Mat object
    img_decode = cv.imdecode(image, cv.IMREAD_COLOR)
    cv.imshow("Display window", img_decode)
    k = cv.waitKey(0)
    if k == ord("s"):
        cv.imwrite([your fileaddress/filename], img_decode)

except Exception as err:
    print(f'Other error occurred: {err}')