Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Currently, we are widely soliciting contributions from everyone. Friends are welcome to submit articles to us, and you can receive corresponding remuneration. For detailed information, please click:Call for Papers.

Recruitment: Looking for a friend with a deep understanding of deep learning to participate in the operation of the knowledge community and the arrangement of daily tasks. Specific business and salary can be discussed in detail after scanning the QR code at the end of the article. Please note “Knowledge Community Operation” before adding.

Author丨woshigaowei5146 @CSDN

Table of Contents

Preparation

Configuration

Testing

Program

Color Recognition Tracking

Face Recognition

Gesture Recognition

Shape Recognition

Barcode Recognition

QR Code Recognition

Problem Solving

module ‘cv2’ has no attribute ‘dnn’
ImportError:numpy.core.multiarray failed to import 1121:error:(-2:Unspecified error)FAILED:fs.is_open(). Can’t open
Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Preparation

  • Raspberry Pi 4B

  • USB Plug-and-Play Camera

Configuration

Install python-opencv, refer to: https://blog.csdn.net/weixin_45911959/article/details/122709090

Install numpy, pip3 install -U numpy

Install opencv-python, opencv-contrib-python, refer to: https://blog.csdn.net/weixin_57605235/article/details/121512923

Testing

Image:

import cv2

a=cv2.imread("/home/pi/2020-06-15-162551_1920x1080_scrot.png")
cv2.imshow("test",a)
cv2.waitKey()
cv2.destroyAllWindows()

Video:

import cv2

cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    cv2.imshow('frame', frame)
    # This step is necessary, otherwise the image cannot be displayed
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything is done, release the capture
cap.release()
cv2.destroyAllWindows()

Program

Color Recognition Tracking

import sys
import cv2
import math
import time
import threading
import numpy as np
import HiwonderSDK.yaml_handle as yaml_handle

if sys.version_info.major == 2:
    print('Please run this program with python3!')
    sys.exit(0)

range_rgb = {
    'red':   (0, 0, 255),
    'blue':  (255, 0, 0),
    'green': (0, 255, 0),
    'black': (0, 0, 0),
    'white': (255, 255, 255)}

__target_color = ('red', 'green', 'blue')
lab_data = yaml_handle.get_yaml_data(yaml_handle.lab_file_path)
    
# Find the largest contour
# The parameter is a list of contours to compare

def getAreaMaxContour(contours):
    contour_area_temp = 0
    contour_area_max = 0
    area_max_contour = None

    for c in contours:  # Iterate through all contours
        contour_area_temp = math.fabs(cv2.contourArea(c))  # Calculate contour area
        if contour_area_temp > contour_area_max:
            contour_area_max = contour_area_temp
            if contour_area_temp > 300:  # Only when the area is larger than 300, the largest area contour is valid, to filter interference
                area_max_contour = c

    return area_max_contour, contour_area_max  # Return the largest contour

detect_color = None
color_list = []
start_pick_up = False
size = (640, 480)

def run(img):
    global rect
    global detect_color
    global start_pick_up
    global color_list
        
    img_copy = img.copy()
    frame_resize = cv2.resize(img_copy, size, interpolation=cv2.INTER_NEAREST)
    frame_gb = cv2.GaussianBlur(frame_resize, (3, 3), 3)
    frame_lab = cv2.cvtColor(frame_gb, cv2.COLOR_BGR2LAB)  # Convert image to LAB space
    color_area_max = None
    max_area = 0
    areaMaxContour_max = 0
    if not start_pick_up:
        for i in lab_data:
            if i in __target_color:
                frame_mask = cv2.inRange(frame_lab,
                                             (lab_data[i]['min'][0],
                                              lab_data[i]['min'][1],
                                              lab_data[i]['min'][2]),
                                             (lab_data[i]['max'][0],
                                              lab_data[i]['max'][1],
                                              lab_data[i]['max'][2]))  # Perform bitwise operation on the original image and mask
                opened = cv2.morphologyEx(frame_mask, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))  # Open operation
                closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, np.ones((3, 3), np.uint8))  # Close operation
                contours = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]  # Find contours
                areaMaxContour, area_max = getAreaMaxContour(contours)  # Find the largest contour
                
                if areaMaxContour is not None:
                    if area_max > max_area:  # Find the largest area
                        max_area = area_max
                        color_area_max = i
                        areaMaxContour_max = areaMaxContour
        
        if max_area > 500:  # If the largest area is found
            rect = cv2.minAreaRect(areaMaxContour_max)
            box = np.int0(cv2.boxPoints(rect))
            y = int((box[1][0]-box[0][0])/2+box[0][0])
            x = int((box[2][1]-box[0][1])/2+box[0][1])
            print('X:',x,'Y:',y) # Print coordinates
            cv2.drawContours(img, [box], -1, range_rgb[color_area_max], 2)
            if not start_pick_up:
                if color_area_max == 'red':  # Red is the largest
                    color = 1
                elif color_area_max == 'green':  # Green is the largest
                    color = 2
                elif color_area_max == 'blue':  # Blue is the largest
                    color = 3
                else:
                    color = 0
                color_list.append(color)
                if len(color_list) == 3:  # Multiple judgments
                    # Take the average value
                    color = int(round(np.mean(np.array(color_list))))
                    color_list = []
                    if color == 1:
                        detect_color = 'red'

                    elif color == 2:
                        detect_color = 'green'

                    elif color == 3:
                        detect_color = 'blue'

                    else:
                        detect_color = 'None'

##    cv2.putText(img, "Color: " + detect_color, (10, img.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.65, detect_color, 2)
    return img

if __name__ == '__main__':
    
    cap = cv2.VideoCapture(-1) # Read camera
    __target_color = ('red',)
    while True:
        ret, img = cap.read()
        if ret:
            frame = img.copy()
            Frame = run(frame)           
            cv2.imshow('Frame', Frame)
            key = cv2.waitKey(1)
            if key == 27:
                break
        else:
            time.sleep(0.01)
    cv2.destroyAllWindows()

Effect:

Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Face Recognition

Utilizes a face dataset trained with Caffe.

import sys
import numpy as np
import cv2
import math
import time
import threading

# Face detection
if sys.version_info.major == 2:
    print('Please run this program with python3!')
    sys.exit(0)

# Threshold
conf_threshold = 0.6

# Model location
modelFile = "/home/pi/mu_code/models/res10_300x300_ssd_iter_140000_fp16.caffemodel"
configFile = "/home/pi/mu_code/models/deploy.prototxt"
net = cv2.dnn.readNetFromCaffe(configFile, modelFile)

frame_pass = True
x1=x2=y1=y2 = 0
old_time = 0

def run(img):
    global old_time
    global frame_pass
    global x1,x2,y1,y2

    if not frame_pass:
        frame_pass = True
        cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2, 8)
        x1=x2=y1=y2 = 0
        return img
    else:
        frame_pass = False

    img_copy = img.copy()
    img_h, img_w = img.shape[:2]
    blob = cv2.dnn.blobFromImage(img_copy, 1, (100, 100), [104, 117, 123], False, False)
    net.setInput(blob)
    detections = net.forward() # Calculate recognition

    for i in range(detections.shape[2]):
        confidence = detections[0, 0, i, 2]
        if confidence > conf_threshold:
            # Convert the coordinates of the recognized person's bounding box back to the original scale
            x1 = int(detections[0, 0, i, 3] * img_w)
            y1 = int(detections[0, 0, i, 4] * img_h)
            x2 = int(detections[0, 0, i, 5] * img_w)
            y2 = int(detections[0, 0, i, 6] * img_h)
            cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2, 8) # Draw a box around the recognized face
            
            X = (x1 + x2)/2
            Y = (y1 + y2)/2
            print('X:',X,'Y:',Y)
    return img

if __name__ == '__main__':

    cap = cv2.VideoCapture(-1) # Read camera

    while True:
        ret, img = cap.read()
        if ret:
            frame = img.copy()
            Frame = run(frame)
            cv2.imshow('Frame', Frame)
            key = cv2.waitKey(1)
            if key == 27:
                break
        else:
            time.sleep(0.01)
    cv2.destroyAllWindows()
Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Gesture Recognition

import os
import sys
import cv2
import math
import time
import numpy as np
import HiwonderSDK.Misc as Misc

if sys.version_info.major == 2:
    print('Please run this program with python3!')
    sys.exit(0)

__finger = 0
__t1 = 0
__step = 0
__count = 0
__get_finger = False

# Initial position
def initMove():
    pass

def reset():
    global __finger, __t1, __step, __count, __get_finger
    __finger = 0
    __t1 = 0
    __step = 0
    __count = 0
    __get_finger = False
    
def init():
    reset()
    initMove()

class Point(object):  # A coordinate point
    x = 0
    y = 0

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

class Line(object):  # A line
    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2

def GetCrossAngle(l1, l2):
    '''
    Calculate the angle between two lines
    :param l1:
    :param l2:
    :return:
    '''
    arr_0 = np.array([(l1.p2.x - l1.p1.x), (l1.p2.y - l1.p1.y)])
    arr_1 = np.array([(l2.p2.x - l2.p1.x), (l2.p2.y - l2.p1.y)])
    cos_value = (float(arr_0.dot(arr_1)) / (np.sqrt(arr_0.dot(arr_0))
                                            * np.sqrt(arr_1.dot(arr_1))))   # Note to convert to float for calculation
    return np.arccos(cos_value) * (180/np.pi)

def distance(start, end):
    """
    Calculate the distance between two points
    :param start: Starting point
    :param end: Ending point
    :return: Return the distance between the two points
    """
    s_x, s_y = start
    e_x, e_y = end
    x = s_x - e_x
    y = s_y - e_y
    return math.sqrt((x**2)+(y**2))

def image_process(image, rw, rh):  # hsv
    '''
    # Light influence, please modify the range of cb
    # The Cr component of normal yellow-skinned people is about 140~160
    Recognize skin color
    :param image: Image
    :return: Recognized binary image
    '''
    frame_resize = cv2.resize(image, (rw, rh), interpolation=cv2.INTER_CUBIC)
    YUV = cv2.cvtColor(frame_resize, cv2.COLOR_BGR2YCR_CB)  # Convert the image to YCrCb
    _, Cr, _ = cv2.split(YUV)  # Split YCrCb
    Cr = cv2.GaussianBlur(Cr, (5, 5), 0)
    
    _, Cr = cv2.threshold(Cr, 135, 160, cv2.THRESH_BINARY +
                          cv2.THRESH_OTSU)  # OTSU Binarization

    # Open operation, remove noise
    open_element = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    opend = cv2.morphologyEx(Cr, cv2.MORPH_OPEN, open_element)
    # Erosion
    kernel = np.ones((3, 3), np.uint8)
    erosion = cv2.erode(opend, kernel, iterations=3)

    return erosion

def get_defects_far(defects, contours, img):
    '''
    Get the farthest point in the convex hull
    '''
    if defects is None and contours is None:
        return None
    far_list = []
    for i in range(defects.shape[0]):
        s, e, f, d = defects[i, 0]
        start = tuple(contours[s][0])
        end = tuple(contours[e][0])
        far = tuple(contours[f][0])
        # Calculate the distance between two points
        a = distance(start, end)
        b = distance(start, far)
        c = distance(end, far)
        # Calculate the angle between fingers
        angle = math.acos((b ** 2 + c ** 2 - a ** 2) /
                          (2 * b * c)) * 180 / math.pi
        # The angle between fingers generally does not exceed 100 degrees
        # Less than 90 degrees
        if angle <= 75:  # 90:
            #cv.circle(img, far, 10, [0, 0, 255], 1)
            far_list.append(far)
    return far_list

def get_max_coutour(cou, max_area):
    '''
    Find the largest contour
    Calculate based on area, after finding the maximum, determine whether it is less than the minimum area, and if it is, give up
    :param cou: Contours
    :return: Return the largest contour
    '''
    max_coutours = 0
    r_c = None
    if len(cou) < 1:
        return None
    else:
        for c in cou:
            # Calculate area
            temp_coutours = math.fabs(cv2.contourArea(c))
            if temp_coutours > max_coutours:
                max_coutours = temp_coutours
                cc = c
        # Determine the largest area among all contours
        if max_coutours > max_area:
            r_c = cc
        return r_c

def find_contours(binary, max_area):
    '''
    CV_RETR_EXTERNAL - Only extract the outermost contour
    CV_RETR_LIST - Extract all contours and place them in a list
    CV_RETR_CCOMP - Extract all contours and organize them into a two-layer hierarchy: the top layer is the outer boundary of the connected domain, and the second layer is the inner boundary of the hole.
    CV_RETR_TREE - Extract all contours and reconstruct the entire hierarchy of nested contours
    method  Approximation method (for all nodes, excluding those using internal approximation CV_RETR_RUNS).
    CV_CHAIN_CODE - Output contour of Freeman chain code. Other methods output polygons (vertex sequence).
    CV_CHAIN_APPROX_NONE - Translate all points from chain code form (convert) to point sequence form.
    CV_CHAIN_APPROX_SIMPLE - Compress horizontal, vertical and diagonal segments, that is, the function only retains the end pixel points;
    CV_CHAIN_APPROX_TC89_L1,
    CV_CHAIN_APPROX_TC89_KCOS - Apply the Teh-Chin chain approximation algorithm. CV_LINK_RUNS - Use a completely different contour extraction algorithm by connecting horizontal fragments with a value of 1.
    :param binary: Incoming binary image
    :return: Return the largest contour
    '''
    # Find all contours
    contours = cv2.findContours(
        binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
    # Return the largest contour
    return get_max_coutour(contours, max_area)

def get_hand_number(binary_image, contours, rw, rh, rgb_image):
    '''
    :param binary_image:
    :param rgb_image:
    :return:
    '''
    # # 2、Find the position of the fingertips
    # # Find contours, return the largest contour
    x = 0
    y = 0
    coord_list = []
    new_hand_list = []  # Get the final finger coordinates

    if contours is not None:
        # Perimeter  0.035 Modify according to recognition situation, the better the recognition, the smaller
        epsilon = 0.020 * cv2.arcLength(contours, True)
        # Contour similarity
        approx = cv2.approxPolyDP(contours, epsilon, True)
        # cv2.approxPolyDP() The parameter 2 (epsilon) is a distance value, which indicates the degree of approach of the polygon contour to the actual contour. The smaller the value, the more accurate; parameter 3 indicates whether it is closed.
        # cv2.polylines(rgb_image, [approx], True, (0, 255, 0), 1)# Draw polygon

        if approx.shape[0] >= 3:  # More than three points are needed for a polygon; a triangle requires three points
            approx_list = []
            for j in range(approx.shape[0]):  # Store all points of the polygon in a list
                # cv2.circle(rgb_image, (approx[j][0][0],approx[j][0][1]), 5, [255, 0, 0], -1)
                approx_list.append(approx[j][0])
            approx_list.append(approx[0][0])    # Add the first point at the end
            approx_list.append(approx[1][0])    # Add the second point at the end

            for i in range(1, len(approx_list) - 1):
                p1 = Point(approx_list[i - 1][0],
                           approx_list[i - 1][1])    # Declare a point
                p2 = Point(approx_list[i][0], approx_list[i][1])
                p3 = Point(approx_list[i + 1][0], approx_list[i + 1][1])
                line1 = Line(p1, p2)    # Declare a line
                line2 = Line(p2, p3)
                angle = GetCrossAngle(line1, line2)     # Get the angle between the two lines
                angle = 180 - angle     #
                # print angle
                if angle < 42:  # Get the angle between the two lines, and if it is less than 37 degrees
                    #cv2.circle(rgb_image, tuple(approx_list[i]), 5, [255, 0, 0], -1)
                    coord_list.append(tuple(approx_list[i]))

        ##############################################################################
        # Remove points between fingers
        # 1、Get the farthest point of the convex hull, the farthest point
        #cv2.drawContours(rgb_image, contours, -1, (255, 0, 0), 1)
        try:
            hull = cv2.convexHull(contours, returnPoints=False)
            # Find convex hull defects. The returned data is 【starting point, ending point, farthest point, approximate distance to the farthest point】
            defects = cv2.convexityDefects(contours, hull)
            # Return the points between fingers
            hand_coord = get_defects_far(defects, contours, rgb_image)
        except:
            return rgb_image, 0
        
        # 2、Remove the farthest point from coord_list
        alike_flag = False
        if len(coord_list) > 0:
            for l in range(len(coord_list)):
                for k in range(len(hand_coord)):
                    if (-10 <= coord_list[l][0] - hand_coord[k][0] <= 10 and
                            -10 <= coord_list[l][1] - hand_coord[k][1] <= 10):    # Compare X and Y axes, remove the close ones
                        alike_flag = True
                        break   #
                if alike_flag is False:
                    new_hand_list.append(coord_list[l])
                alike_flag = False
            # Get the fingertip coordinate list and display
            for i in new_hand_list:
                j = list(tuple(i))
                j[0] = int(Misc.map(j[0], 0, rw, 0, 640))
                j[1] = int(Misc.map(j[1], 0, rh, 0, 480))
                cv2.circle(rgb_image, (j[0], j[1]), 20, [0, 255, 255], -1)
    fingers = len(new_hand_list)

    return rgb_image, fingers


def run(img, debug=False):

    global __act_map, __get_finger
    global __step, __count, __finger

    binary = image_process(img, 320, 240)
    contours = find_contours(binary, 3000)
    img, finger = get_hand_number(binary, contours, 320, 240, img)
    if not __get_finger:
        if finger == __finger:
            __count += 1
        else:
            __count = 0
        __finger = finger
        
    cv2.putText(img, "Finger(s):%d" % __finger, (50, 480 - 30),
                cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 255), 2) # Write the number of recognized fingers on the image
    
    return img 

if __name__ == '__main__':
    
    init()
    cap = cv2.VideoCapture(-1) # Read camera
    while True:
        ret, img = cap.read()
        if ret:
            frame = img.copy()
            Frame = run(frame)           
            frame_resize = cv2.resize(Frame, (320, 240))
            cv2.imshow('frame', frame_resize)
            key = cv2.waitKey(1)
            if key == 27:
                break
        else:
            time.sleep(0.01)
    cv2.destroyAllWindows()
Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Shape Recognition

import sys
import cv2
import math
import time
import threading
import numpy as np
import HiwonderSDK.tm1640 as tm
import RPi.GPIO as GPIO

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

color_range = {
'red': [(0, 101, 177), (255, 255, 255)], 
'green': [(47, 0, 135), (255, 119, 255)], 
'blue': [(0, 0, 0), (255, 255, 115)], 
'black': [(0, 0, 0), (41, 255, 136)], 
'white': [(193, 0, 0), (255, 250, 255)], 
}

if sys.version_info.major == 2:
    print('Please run this program with python3!')
    sys.exit(0)
    
range_rgb = {
    'red': (0, 0, 255),
    'blue': (255, 0, 0),
    'green': (0, 255, 0),
    'black': (0, 0, 0),
    'white': (255, 255, 255),
}

# Find the largest contour
# The parameter is a list of contours to compare

def getAreaMaxContour(contours):
    contour_area_temp = 0
    contour_area_max = 0
    area_max_contour = None

    for c in contours:  # Iterate through all contours
        contour_area_temp = math.fabs(cv2.contourArea(c))  # Calculate contour area
        if contour_area_temp > contour_area_max:
            contour_area_max = contour_area_temp
            if contour_area_temp > 50:  # Only when the area is larger than 50, the largest area contour is valid, to filter interference
                area_max_contour = c

    return area_max_contour, contour_area_max  # Return the largest contour

shape_length = 0

def move():
    global shape_length
    
    while True:
        if shape_length == 3:
            print('Triangle')
            ## Display 'Triangle'
            tm.display_buf = (0x80, 0xc0, 0xa0, 0x90, 0x88, 0x84, 0x82, 0x81,
                              0x81, 0x82, 0x84,0x88, 0x90, 0xa0, 0xc0, 0x80)
            tm.update_display()
            
        elif shape_length == 4:
            print('Rectangle')
            ## Display 'Rectangle'
            tm.display_buf = (0x00, 0x00, 0x00, 0x00, 0xff, 0x81, 0x81, 0x81,
                              0x81, 0x81, 0x81,0xff, 0x00, 0x00, 0x00, 0x00)
            tm.update_display()
            
        elif shape_length >= 6:           
            print('Circle')
            ## Display 'Circle'
            tm.display_buf = (0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x41,
                              0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00)
            tm.update_display()
            
        time.sleep(0.01)
               
# Run a child thread
th = threading.Thread(target=move)
th.setDaemon(True)
th.start()

shape_list = []
action_finish = True

if __name__ == '__main__':
    
    cap = cv2.VideoCapture(-1)
    while True:
        ret,img = cap.read()
        if ret:
            img_copy = img.copy()
            img_h, img_w = img.shape[:2]
            frame_gb = cv2.GaussianBlur(img_copy, (3, 3), 3)      
            frame_lab = cv2.cvtColor(frame_gb, cv2.COLOR_BGR2LAB)  # Convert image to LAB space
            max_area = 0
            color_area_max = None    
            areaMaxContour_max = 0

            if action_finish:
                for i in color_range:
                    if i != 'white':
                        frame_mask = cv2.inRange(frame_lab, color_range[i][0], color_range[i][1])  # Perform bitwise operation on the original image and mask
                        opened = cv2.morphologyEx(frame_mask, cv2.MORPH_OPEN, np.ones((6,6),np.uint8))  # Open operation
                        closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, np.ones((6,6),np.uint8)) # Close operation
                        contours = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]  # Find contours
                        areaMaxContour, area_max = getAreaMaxContour(contours)  # Find the largest contour
                        if areaMaxContour is not None:
                            if area_max > max_area:# Find the largest area
                                max_area = area_max
                                color_area_max = i
                                areaMaxContour_max = areaMaxContour
            if max_area > 200:                   
                cv2.drawContours(img, areaMaxContour_max, -1, (0, 0, 255), 2)
                # Recognize shape
                # Perimeter  0.035 Modify according to recognition situation, the better the recognition, the smaller
                epsilon = 0.035 * cv2.arcLength(areaMaxContour_max, True)
                # Contour similarity
                approx = cv2.approxPolyDP(areaMaxContour_max, epsilon, True)
                shape_list.append(len(approx))
                if len(shape_list) == 30:
                    shape_length = int(round(np.mean(shape_list)))                            
                    shape_list = []
                    print(shape_length)
                    
            frame_resize = cv2.resize(img, (320, 240))
            cv2.imshow('frame', frame_resize)
            key = cv2.waitKey(1)
            if key == 27:
                break
        else:
            time.sleep(0.01)
    my_camera.camera_close()
    cv2.destroyAllWindows()

The approxPolyDP() function is used to approximate a continuous smooth curve into a polygon.

For example, in the code “approx=cv2.approxPolyDP(areaMaxContour_max,epsilon,True)”, the parameters in parentheses mean:

The first parameter “areaMaxContour_max” is the input shape contour;

The second parameter “epsilon” is the distance value, which indicates the degree of approach of the polygon contour to the actual contour. The smaller the value, the more accurate;

The third parameter “True” indicates that the contour is a closed curve.

The output of the cv2.approxPolyDP() function is the vertex coordinates of the approximated polygon, and the shape is judged based on the number of vertices.

Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Barcode Recognition

First, install pyzbar, pip3 install pyzbar

import cv2
import sys
from pyzbar import pyzbar

if sys.version_info.major == 2:
    print('Please run this program with python3!')
    sys.exit(0)

def run(image):
    # Find barcodes in the image and decode each barcode
    barcodes = pyzbar.decode(image)
    # Loop through detected barcodes
    for barcode in barcodes:
        # Extract the bounding box position of the barcode
        (x, y, w, h) = barcode.rect
        # Draw a box around the barcode in the image
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)

        barcodeData = barcode.data.decode("utf-8")
        barcodeType = barcode.type
        # Draw the barcode data and barcode type on the image
        text = "{} ({})".format(barcodeData, barcodeType)
        cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

    return image

if __name__ == '__main__':
    
    cap = cv2.VideoCapture(-1) # Read camera
    
    while True:
        ret, img = cap.read()
        if ret:
            frame = img.copy()
            Frame = run(frame)           
            cv2.imshow('Frame', Frame)
            key = cv2.waitKey(1)
            if key == 27:
                break
        else:
            time.sleep(0.01)
    cv2.destroyAllWindows()
Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

QR Code Recognition

Install apriltag, found installation failed. Still using the old method to download locally and then install.

At https://www.piwheels.org/simple/apriltag/, I downloaded apriltag-0.0.16-cp37-cp37m-linux_armv7l.whl.

Use FileZilla to transfer to Raspberry Pi, open the directory where the whl file is located on Raspberry Pi, and install the whl file, showing successful installation.

cd /home/pi/Downloads
sudo pip3 install apriltag-0.0.16-cp37-cp37m-linux_armv7l.whl
Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi
import sys
import cv2
import math
import time
import threading
import numpy as np
import apriltag

# apriltag detection

if sys.version_info.major == 2:
    print('Please run this program with python3!')
    sys.exit(0)

object_center_x = 0.0
object_center_y = 0.0

# Detect apriltag
detector = apriltag.Detector(searchpath=apriltag._get_demo_searchpath())
def apriltagDetect(img):
    global object_center_x, object_center_y
    
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    detections = detector.detect(gray, return_image=False)

    if len(detections) != 0:
        for detection in detections:                       
            corners = np.rint(detection.corners)  # Get four corner points
            cv2.drawContours(img, [np.array(corners, np.int)], -1, (0, 255, 255), 2)

            tag_family = str(detection.tag_family, encoding='utf-8')  # Get tag_family
            tag_id = int(detection.tag_id)  # Get tag_id

            object_center_x, object_center_y = int(detection.center[0]), int(detection.center[1])  # Center point
            
            return tag_family, tag_id
            
    return None, None

def run(img):
    global state
    global tag_id
    global action_finish
    global object_center_x, object_center_y
     
    img_h, img_w = img.shape[:2]
    
    tag_family, tag_id = apriltagDetect(img) # apriltag detection
    
    if tag_id is not None:
        print('X:',object_center_x,'Y:',object_center_y)
        cv2.putText(img, "tag_id: " + str(tag_id), (10, img.shape[0] - 30), cv2.FONT_HERSHEY_SIMPLEX, 0.65, [0, 255, 255], 2)
        cv2.putText(img, "tag_family: " + tag_family, (10, img.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.65, [0, 255, 255], 2)
    else:
        cv2.putText(img, "tag_id: None", (10, img.shape[0] - 30), cv2.FONT_HERSHEY_SIMPLEX, 0.65, [0, 255, 255], 2)
        cv2.putText(img, "tag_family: None", (10, img.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.65, [0, 255, 255], 2)
    
    return img

if __name__ == '__main__':
    
    cap = cv2.VideoCapture(-1) # Read camera
    
    while True:
        ret, img = cap.read()
        if ret:
            frame = img.copy()
            Frame = run(frame)           
            cv2.imshow('Frame', Frame)
            key = cv2.waitKey(1)
            if key == 27:
                break
        else:
            time.sleep(0.01)
    cv2.destroyAllWindows()
Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Problem Solving

module ‘cv2’ has no attribute ‘dnn’

Try the following commands, all have issues, either reporting errors or showing that python-opencv is not recognized, changing mirrors does not help:

sudo apt install python-opencv 或 sudo apt install python3-opencv 

sudo apt-get install opencv-python
sudo apt-get install opencv-contrib-python

pip install opencv-contrib-python
pip install opencv-python
sudo apt install python-opencv 或 sudo apt install python3-opencv 

sudo apt-get install opencv-python
sudo apt-get install opencv-contrib-python

pip install opencv-contrib-python
pip install opencv-python

Finally, successfully installed by downloading the local file. First, update the Raspberry Pi system and files habitually.

sudo apt-get update 
sudo apt-get upgrade 

If the download speed is too slow, consider changing the source.

1) Use the command "sudo nano /etc/apt/sources.list" to edit the sources.list file, comment out all the contents of the original file, and append the following content:
deb http://mirrors.aliyun.com/raspbian/raspbian/ buster main contrib non-free rpi
deb-src http://mirrors.aliyun.com/raspbian/raspbian/ buster main contrib non-free rpi

Use Ctrl+O shortcut to save the file, Ctrl+X to exit.

2) Use the command "sudo nano /etc/apt/sources.list.d/raspi.list" to edit the raspi.list file, comment out all the contents of the original file, and append the following content:
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main
deb-src http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main

Use Ctrl+O shortcut to save the file, Ctrl+X to exit.

3) Execute the command "sudo apt-get update".

4) To accelerate the installation speed of Python pip, change the Python software source. The method is: open the Raspberry Pi command line,
input the following command:
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip install pip -U

5) Finally, enter the command "sudo reboot" to restart the Raspberry Pi.

Download the whl file and transfer it to the Raspberry Pi. On the computer, open https://www.piwheels.org/simple/opencv-python/

Download the whl file corresponding to your python version, I downloaded opencv_python-3.4.10.37-cp37-cp37m-linux_armv7l.whl

cp37 indicates the python version, armv7 indicates the processor architecture, Raspberry Pi 4B chooses armv7

Use FileZilla to transfer it to the Raspberry Pi, open the directory where the whl file is located on the Raspberry Pi, and install the whl file, showing successful installation of opencv-python.

cd /home/pi/Downloads
sudo pip3 install opencv_python-3.4.10.37-cp37-cp37m-linux_armv7l.whl

Reference: https://blog.csdn.net/weixin_57605235/article/details/121512923

ImportError:numpy.core.multiarray failed to import

First uninstall the low version of numpy, then install the new version of numpy, that is

pip uninstall numpy
pip install -U numpy

From https://blog.csdn.net/qq_25603827/article/details/107824977

Invalid.

pip install numpy --upgrade --force

From http://www.manongjc.com/article/38668.html

Invalid.

Check the local numpy version:

pip show numpy

When we install opencv-python, the corresponding numpy version is:

So downgrade numpy:

 pip install -U numpy==1.14.5 -i https://pypi.mirrors.ustc.edu.cn/simple/

From https://zhuanlan.zhihu.com/p/280702247

Invalid.

Finally, with pip3 install -U numpy succeeded. Therefore, it is best to use pip3 with python3. There are many attempts on the internet, some have upgraded versions, some have downgraded versions, all kinds of strange phenomena emerge, and the statements vary. Reference:

https://blog.csdn.net/Robin_Pi/article/details/120544691 https://zhuanlan.zhihu.com/p/29026597

1121:error:(-2:Unspecified error) FAILED: fs.is_open(). Can’t open

After searching for a long time, I found that there was an extra point at the beginning.

If you think it is good, please give a “like” or “look”.

CV technology refers to Nan created a computer vision technology group chat and a free version of the knowledge community. Currently, the number of people in the community has reached 700+, and the number of topics has reached 200+.

Every day, some assignments will be published in the knowledge community, to guide everyone to learn something. Everyone can clock in and learn according to the assignments.

The technical group will send the latest conference papers in the past few days every day. Everyone can choose the papers they are interested in to read, and continue to follow the latest technology. If you finish reading and write an interpretation to submit to us, you can also receive remuneration.

How to join the group and community: Scan the QR code at the end of the article.

—-Copyright Statement—-

For academic sharing only, please contact to delete if there is any infringement.

Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Currently, we are widely soliciting contributions from everyone. Friends are welcome to submit articles to us, and you can receive corresponding remuneration. For detailed information, please click:Call for Papers

Please note “Research Direction-City-Submission” before adding.

Join the free version of the knowledge community, please note before adding: “Research Direction-City-Knowledge Community”.

Using OpenCV for Image Tracking and Face Recognition on Raspberry Pi

Leave a Comment

×