Playing with the Sparkfun HM01b0 (Color) camera

KurtE

Senior Member+
Not sure why it is so expensive $55, but I was curious about it a few reasons.

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.
1758152963915.png


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);
    }
  }

}
First attempt was off as I forgot we mirror and flip the image in the camera. So the pixels in the grid are different.
1758153199228.png

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
 
$55 seems high when they have the bare camera/sensor for $11 - does have the cable connector and a few things on the PCB.
Decent job on the colors - black and red show for sure in the one pic.
 
Typically these camera sensors have separate voltage requirements for analog/digital/IO stages so the board would take care of all that. Wouldn't say that's worth an extra $45 though.
This one also has a built in 24mhz oscillator.

But I assume that the other cameras with similar form factors also have to handle the voltage requirements.
For example, the ones sold by Arducam/Arduino

Monochrome:
HM01b0 QVGA: https://www.arducam.com/hm01b0-qvga-monochrome-dvp-camera-module-for-arduino-giga-r1-wifi-board.html $6.99
Problem with this one is they only routed 4 data lines

HM0360 VGA: https://www.arducam.com/hm0360-vga-monochrome-dvp-camera-module-for-arduino-giga-r1-wifi-board.html $9.99

Color:
OV7675: $5.95
GC2145: 2MP $9.99

Adafruit: OV5640 5mp $10-$20
Waveshare OV2640: 2MP several $13

But did not find many with the HM01b0 with the 8 bit data bits connected...
 
Back
Top