Note

This is the documentation for the latest development branch and may refer to features that are not available in released versions. If you are looking for the documentation for a specific release, use the drop-down menu on the left and select the desired version.

Color Recognition (find_blobs) Routine Explanation

Color Recognition (find_blobs) Routine Explanation#

Overview#

find_blobs is an image processing function of OpenMV, used to find and identify “blobs” in an image. These blobs refer to regions in the image with similar color or brightness. This function is commonly used in visual detection and recognition applications, such as object tracking, color recognition, etc.

CanMV supports OpenMV algorithms and can also use find_blobs.

Function Explanation#

Basic Usage#

blobs = img.find_blobs([thresholds], area_threshold=area_threshold, pixels_threshold=pixels_threshold, merge=True, margin=0)

Parameter Explanation#

  • thresholds: This is a list containing color ranges, used to define the color range of the blobs to look for. It is usually a tuple containing two or three elements. For example, (100, 200, -64, 127, -128, 127) represents a range in the HSV color space, where the first and second values are Hue, the third and fourth are Saturation, and the last two are Value.

  • area_threshold: The area threshold for blobs. Only blobs with an area greater than this value will be returned. The default value is 0.

  • pixels_threshold: The pixel count threshold for blobs. Only blobs containing more pixels than this value will be returned. The default value is 0.

  • merge: Whether to merge adjacent blobs. When set to True, adjacent blobs will be merged into one large blob; when set to False, blobs will not be merged. The default value is True.

  • margin: The margin used when merging blobs. Set to a positive integer, indicating the maximum distance when merging blobs. The default value is 0.

Return Value#

The find_blobs function returns a list containing blob information. Each blob is a Blob object, which typically contains the following attributes:

  • cx and cy: The center coordinates of the blob.

  • x and y: The coordinates of the top-left corner of the blob.

  • w and h: The width and height of the blob.

  • area: The area of the blob (pixel count).

Example#

Only a single color tracking example is listed here. For specific demos, please refer to the routines in the virtual U-disk that comes with the firmware.

# Single Color Code Tracking Example
#
# This example shows off single color code tracking with the CanMV camera.
#
# Color codes are or'ed to form blob colors. The below example tracks
# color blobs which only contain the following color codes.
import time, os, gc, sys, math

from media.sensor import *
from media.display import *
from media.media import *

DETECT_WIDTH = 640
DETECT_HEIGHT = 480

# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max)
# The below thresholds track in general red/green things. You may
# wish to tune them...
thresholds = [(12, 100, -47, 14, -1, 58), # generic_red_thresholds -> index is 0 so code == (1 << 0)
              (30, 100, -64, -8, -32, 32)] # generic_green_thresholds -> index is 1 so code == (1 << 1)
# codes are or'ed to form "find_blobs" with merge=True

# Only blobs that pass the pixels_threshold and area_threshold
# requirements will be returned by "find_blobs" below. You should
# adjust "pixels_threshold" and "area_threshold" for how your object
# should look on the screen. Merge is True so you get color codes
# that may be touching each other.

sensor = None

try:
    # Construct a Sensor object with default configuration
    sensor = Sensor(width = DETECT_WIDTH, height = DETECT_HEIGHT)
    # sensor reset
    sensor.reset()
    # Set horizontal mirror
    # sensor.set_hmirror(False)
    # Set vertical flip
    # sensor.set_vflip(False)
    # Set channel 0 output size
    sensor.set_framesize(width = DETECT_WIDTH, height = DETECT_HEIGHT)
    # Set channel 0 output format
    sensor.set_pixformat(Sensor.RGB565)

    # Set display. If the screen you selected cannot be lit, please refer to the API documentation of k230_canmv_display_module_api_manual for configuration. Four display methods are given below
    # Use HDMI as display output, set to VGA
    # Display.init(Display.LT9611, width = 640, height = 480, to_ide = True)

    # Use HDMI as display output, set to 1080P
    # Display.init(Display.LT9611, width = 1920, height = 1080, to_ide = True)

    # Use LCD as display output
    # Display.init(Display.ST7701, to_ide = True)

    # Use IDE as output
    Display.init(Display.VIRT, width = DETECT_WIDTH, height = DETECT_HEIGHT, fps = 100)

    # Initialize media manager
    MediaManager.init()
    # sensor start run
    sensor.run()

    fps = time.clock()

    while True:
        fps.tick()

        # Check if should exit
        os.exitpoint()
        img = sensor.snapshot()

        for blob in img.find_blobs(thresholds, pixels_threshold=100, area_threshold=100, merge=True):
            if blob.code() == 3: # r/g code == (1 << 1) | (1 << 0)
                # These values depend on the blob not being circular - otherwise they will be unstable
                # if blob.elongation() > 0.5:
                #     img.draw_edges(blob.min_corners(), color=(255,0,0))
                #     img.draw_line(blob.major_axis_line(), color=(0,255,0))
                #     img.draw_line(blob.minor_axis_line(), color=(0,0,255))
                # These values are stable all the time
                img.draw_rectangle([v for v in blob.rect()])
                img.draw_cross(blob.cx(), blob.cy())
                # Note - the blob rotation is unique to 0-180 only.
                img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)

        # Draw results to the screen
        Display.show_image(img)
        gc.collect()

        print(fps.fps())
except KeyboardInterrupt as e:
    print(f"user stop")
except BaseException as e:
    print(f"Exception '{e}'")
finally:
    # sensor stop run
    if isinstance(sensor, Sensor):
        sensor.stop()
    # deinit display
    Display.deinit()

    os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
    time.sleep_ms(100)

    # Release media buffer
    MediaManager.deinit()

Tip

For specific interface definitions, please refer to find_blobs

Comments list
Comments
Log in