0

Background: my goal is to learn OpenCV and practice with barcode detection/decoding to make a barcode matching system using 2 cameras, or camera and barcode scanner.

I have an older industrial camera (IDS Ueye UI221) that I'm tinkering with. IDS provided a python-based sample application that does the basic camera connections (memory, color space detection, etc). The camera feed is good and clear, my barcodes are reading and decoding correctly. I've got an overlay of the decoded data for human-readability. Splendid! But, I'm trying to render the overlay in color (increased readability), and it always comes out white.

White bounding box (cv2.rectangle()) and 'decode' placeholder text displaying putText().

I would like the putText() overlay to be in any color other than white for now, but will likely go with (255, 0 , 0) RGB -- but even if openCV wants to make it BGR and I get blue text and box, I don't care!

I know I'm probably missing something basic, but after reading many, including: detect color space with openCV , How does one convert a grayscale image to RGB in OpenCV (Python)?

I tried putting cv2.cvtColor(frame, cv2.COLOR_GRAY2RGB) in before I overlay the color putText() stuff, thinking maybe I can't overlay color on grayscale? Well, I look forward to learning from any replies I receive. Thanks a bunch!

from pyueye import ueye
import numpy as np
import cv2
from pyzbar.pyzbar import decode
import sys`

# identify camera color space -- programmed by the camera manufacturer


if:
   pass

elif int.from_bytes(sInfo.nColorMode.value, byteorder='big') == ueye.IS_COLORMODE_MONOCHROME:
    # for color camera models use RGB32 mode
    m_nColorMode = ueye.IS_CM_MONO8
    nBitsPerPixel = ueye.INT(8)
    bytes_per_pixel = int(nBitsPerPixel / 8)
    print("IS_COLORMODE_MONOCHROME: ", )
    print("\tm_nColorMode: \t\t", m_nColorMode)
    print("\tnBitsPerPixel: \t\t", nBitsPerPixel)
    print("\tbytes_per_pixel: \t\t", bytes_per_pixel)
    print()

# Continuous image display
while nRet == ueye.IS_SUCCESS:

    # In order to display the image in an OpenCV window we need to extract the data of our image memory
    array = ueye.get_data(pcImageMemory, width, height, nBitsPerPixel, pitch, copy=False)

    # bytes_per_pixel = int(nBitsPerPixel / 8)

    # ...reshape it in an numpy array...
    frame = np.reshape(array, (height.value, width.value, bytes_per_pixel))

    # ...resize the image by a half
    # frame = cv2.resize(frame, (0, 0), fx=0.5, fy=0.5)

    # ...double the image size for easier readability
    frame = cv2.resize(frame, (0, 0), fx=2, fy=2)
    
# HERE WAS MY MISTAKE :( I needed to assign the change to color not just try # to call the function
    # cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)

    **frame =** cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)


# ---------------------------------------
    # Include image data processing here

    processed_image = decode(frame)
    print(processed_image)  # just for troubleshooting aiming the camera and stuff

    # adding bounding box around the scanned barcode and human-readable content
    for barcode in processed_image:
        (x, y, w, h) = barcode.rect
        cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 5)

        # font
        font = cv2.FONT_HERSHEY_PLAIN

        # org
        org = (x, y+h+30)

        # fontScale
        fontScale = 3

        # Blue color in BGR
        color = (255, 0, 0)

        # Line thickness of 2 px
        thickness = 2

        # Using cv2.putText() method
        cv2.putText(frame, 'Decode', org, font, fontScale, color, thickness, cv2.LINE_AA)

Here is what I get from console output:

START

IS_COLORMODE_MONOCHROME: m_nColorMode: 6, nBitsPerPixel: 8, bytes_per_pixel: 1

Camera model: UI221xSE-M, Camera serial no.: 4002909292, Maximum image width: 640, Maximum image height: 480

[] [Decoded(data=b'https:/testtesttest', type='QRCODE', rect=Rect(left=887, top=109, width=328, height=312), polygon=[Point(x=887, y=421), Point(x=1215, y=418), Point(x=1206, y=109), Point(x=888, y=115)], quality=1, orientation='UP'), Decoded(data=b'https://testtesttest', type='QRCODE', rect=Rect(left=248, top=114, width=341, height=320), polygon=[Point(x=248, y=433), Point(x=579, y=434), Point(x=589, y=114), Point(x=270, y=122)], quality=1, orientation='UP')]

The video output is shown in the first screenshot at the top.

CBJFan2009
  • 25
  • 5
  • 1
    You're drawing onto a single channel image (i.e. grayscale/monochrome -> can not represent colour). You don't "have a colour overlay", you're using OpenCV drawing function to draw into that grayscale image. When the destination is single channel, only the first component of the colour tuple is used (in this case `255`, which is full intensity, i.e. white). – Dan Mašek Feb 24 '23 at 17:30
  • Dan, thank you. I assumed this was the problem. Since I tried the cv2.cvtColor(frame, cv2.COLOR_GRAY2RGB) before applying the overlay and it still didn't apply color, what other step is needed? Is there something else that can create the needed channels? – CBJFan2009 Feb 24 '23 at 17:36
  • Update your [mcve] to include the colour conversion you tried, as well as how you output (save or display) the result. – Dan Mašek Feb 24 '23 at 17:59
  • Convert your frame to 3-channels, i.e. BGR using cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR) or use cv2.merge([frame,frame,frame]) before drawing text. Then you should be able to draw your text in color on it on the 3-channel version of your frame. – fmw42 Feb 24 '23 at 21:14
  • Holy crap! I'm so stupid. I know what I did wrong, now. I had: 'cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR' I forgot to do assign it over frame like this: 'frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR' I feel like a dolt. – CBJFan2009 Feb 28 '23 at 11:57

0 Answers0