arduino-libraries / Arduino_OV767X

Official OV767X Library for Arduino , currently supports OV7670 and OV7675 cameras
https://www.arduino.cc/reference/en/libraries/arduino_ov767x/
GNU General Public License v2.0
68 stars 25 forks source link

feature request: RGB565 convert to RGB888 function #11

Closed hpssjellis closed 3 years ago

hpssjellis commented 3 years ago

Many machine learning programs expect RGB888 image format, wondering if a function that does that could be included in this library

I am loading my images to EdgeImpulse and using this conversion

void r565_to_rgb(uint16_t color, uint8_t *r, uint8_t *g, uint8_t *b) {

    *r = (color & 0xF800) >> 8;
    *g = (color & 0x07E0) >> 3;
    *b = (color & 0x1F) << 3;
}

I get an image like this. Note the image has already been cropped to 48x48 so the it will look grainy.

frame06

which becomes slightly better with this conversion

void r565_to_rgb(uint16_t color, uint8_t *r, uint8_t *g, uint8_t *b) {

      *r = ((((color >> 3) & 0x1F) * 527) + 23) >> 6;
      *g = ((((((color & 0xE0) >> 5) | ((color & 0x03) << 3)) & 0x3F) * 259) + 33) >> 6;
      *b = (((color & 0x1F) * 527) + 23) >> 6;
}

frame07-nano-fast06

Any suggestions on how to better convert the OV7670 RGB565 output?

colbybanbury commented 3 years ago

I had the same issue trying the read the raw bytes in python. I fixed it by swapping the bytes of the int16 pixel (Big-endian to little-endian).

Here's the python code I used which takes from the pde file included on this github:

from matplotlib import pyplot as plt
import numpy as np
import struct

raw_bytes = np.array([ 
#copy image bytes here in this format (0x9EF7, 0xFCD6...)
        ], dtype="i2")
image = np.zeros((len(raw_bytes),3), dtype=int)

for i in range(len(raw_bytes)):
    #read 16-bit pixel
    pixel = struct.unpack('>h', raw_bytes[i])[0] #unpack will switch the endianness

    #convert RGB565 to RGB 24-bit
    r = ((pixel >> 11) & 0x1f) << 3;
    g = ((pixel >> 5) & 0x3f) << 2;
    b = ((pixel >> 0) & 0x1f) << 3;
    image[i] = [r,g,b]

image = np.reshape(image,(120, 160,3))

plt.imshow(image)
plt.show()

In C you should be able to swap struct.unpack for something like pixel = (raw_bytes[i]>>8) | (raw_bytes[i]<<8);

hpssjellis commented 3 years ago

@colbybanbury Thanks so much, that makes sense now why everything I tried didn't seem to improve anything.

Only took a few minutes to solve my issue. pixel = (raw_bytes[i]>>8) | (raw_bytes[i]<<8); was the solution. The image is cropped to 80x80 and I think the camera is a bit out of focus.

Thanks so much. image

colbybanbury commented 3 years ago

Glad I could help!