KurtE
Senior Member+
SparkFun Red Vision Camera Board - HM01B0 (Color)
The SparkFun Red Vision Camera Board makes the 320x320 Himax© HM01B0 camera module simple to use by converting its pins to three sets of standard PTH headers.
There is a PR request in Zephyr to get the basic HM01b0 installed in the Video Devices. It is a pretty bare implementation, where the developer
is doing it as part of a another PR to support for it using the ESP32-Pico. It was setup to use the 1 bit transfer mode (Serial). The Arducam version
uses 4 bit transfers, and I wanted to play with the camera with 8 bit transfer... (Images are the same, but how many data bits get transferred per pixel clock).
The only 8 bit version I had was the Portenta H7 Vision Shield which uses it with 8 bit transfers.
So I wanted one that has the Arducam/Arduino Pin layout (which I have on my Teensy boards as well).
And I was curious about color. It outputs in Bayer mode...
Currently playing on it using the Teensy_camera library... Yesterday soldered the headers and got it to talk to our library, currently on the Micromod using 8 bit FlexIO.
And I can output images from it using our grayscale output.
Today I hacked up a quick and dirty attempt at converting the Bayer output to RGB565...
Note: I don't use the full image of 324x244, but only 320x240 where I still use some of the rows and columns outside of that to fill color.
Code:
// Note The resulting image will lose 4 rows and columns 324x244 -> 320x240
#define BAYER_INDEX(x, y, w) ((y) * (w) + (x))
void convert_bayer_image_to_rgb565(uint8_t *bayer, uint16_t *rgb, uint16_t width, uint16_t height) {
uint16_t r, g, b;
for (uint16_t y = 2; y < (height - 2); y++) {
for (uint16_t x = 2; x < (width - 2); x++) {
#ifdef MIRROR_FLIP_CAMERA
if (y & 1) { // GREEN BLUE row
if (x & 1) { // red
b = bayer[BAYER_INDEX(x, y, width)];
g = (bayer[BAYER_INDEX(x, y + 1, width)] + bayer[BAYER_INDEX(x, y - 1, width)] + bayer[BAYER_INDEX(x + 1, y, width)] + bayer[BAYER_INDEX(x - 1, y, width)]) / 4;
r = (bayer[BAYER_INDEX(x + 1, y + 1, width)] + bayer[BAYER_INDEX(x + 1, y - 1, width)] + bayer[BAYER_INDEX(x - 1, y + 1, width)] + bayer[BAYER_INDEX(x - 1, y - 1, width)]) / 4;
} else { // green
b = (bayer[BAYER_INDEX(x, y + 1, width)] + bayer[BAYER_INDEX(x, y - 1, width)]) / 2;
g = bayer[BAYER_INDEX(x, y, width)];
r = (bayer[BAYER_INDEX(x + 1, y, width)] + bayer[BAYER_INDEX(x - 1, y, width)]) / 2;
}
} else { // RED GREEN row)
if (x & 1) { //green
b = (bayer[BAYER_INDEX(x, y + 1, width)] + bayer[BAYER_INDEX(x, y - 1, width)]) / 2;
g = bayer[BAYER_INDEX(x, y, width)];
r = (bayer[BAYER_INDEX(x + 1, y, width)] + bayer[BAYER_INDEX(x - 1, y, width)]) / 2;
} else { // blue
b = (bayer[BAYER_INDEX(x + 1, y + 1, width)] + bayer[BAYER_INDEX(x + 1, y - 1, width)] + bayer[BAYER_INDEX(x - 1, y + 1, width)] + bayer[BAYER_INDEX(x - 1, y - 1, width)]) / 4;
g = (bayer[BAYER_INDEX(x, y + 1, width)] + bayer[BAYER_INDEX(x, y - 1, width)] + bayer[BAYER_INDEX(x + 1, y, width)] + bayer[BAYER_INDEX(x - 1, y, width)]) / 4;
r = bayer[BAYER_INDEX(x, y, width)];
}
}
#else
if (y & 1) { // GREEN RED row
if (x & 1) { // red
r = bayer[BAYER_INDEX(x, y, width)];
g = (bayer[BAYER_INDEX(x, y + 1, width)] + bayer[BAYER_INDEX(x, y - 1, width)] + bayer[BAYER_INDEX(x + 1, y, width)] + bayer[BAYER_INDEX(x - 1, y, width)]) / 4;
b = (bayer[BAYER_INDEX(x + 1, y + 1, width)] + bayer[BAYER_INDEX(x + 1, y - 1, width)] + bayer[BAYER_INDEX(x - 1, y + 1, width)] + bayer[BAYER_INDEX(x - 1, y - 1, width)]) / 4;
} else { // green
r = (bayer[BAYER_INDEX(x, y + 1, width)] + bayer[BAYER_INDEX(x, y - 1, width)]) / 2;
g = bayer[BAYER_INDEX(x, y, width)];
b = (bayer[BAYER_INDEX(x + 1, y, width)] + bayer[BAYER_INDEX(x - 1, y, width)]) / 2;
}
} else { // BLUE GREEN row)
if (x & 1) { //green
r = (bayer[BAYER_INDEX(x, y + 1, width)] + bayer[BAYER_INDEX(x, y - 1, width)]) / 2;
g = bayer[BAYER_INDEX(x, y, width)];
b = (bayer[BAYER_INDEX(x + 1, y, width)] + bayer[BAYER_INDEX(x - 1, y, width)]) / 2;
} else { // blue
r = (bayer[BAYER_INDEX(x + 1, y + 1, width)] + bayer[BAYER_INDEX(x + 1, y - 1, width)] + bayer[BAYER_INDEX(x - 1, y + 1, width)] + bayer[BAYER_INDEX(x - 1, y - 1, width)]) / 4;
g = (bayer[BAYER_INDEX(x, y + 1, width)] + bayer[BAYER_INDEX(x, y - 1, width)] + bayer[BAYER_INDEX(x + 1, y, width)] + bayer[BAYER_INDEX(x - 1, y, width)]) / 4;
b = bayer[BAYER_INDEX(x, y, width)];
}
}
#endif
*rgb++ = CL(r, g, b);
}
}
}
I know it is not great, but at least getting something. I am hitting an issue in our library that the first image comes through, but
the subsequent ones are sort botched, like not fully synced or the like... will investigate. Also may try it on T4.1 with CSI
Not sure if this will go anywhere, but just having some fun