Reconocimiento de medidores de puntero mediante el método de visión tradicional

Es más adecuado para algunas escenas especiales y cuando el número de instrumentos es pequeño.

encontrar el área objetivo

Utilice la etiqueta para enmarcar el rango del instrumento y convertirlo:

data = json.load(open(mask_path, encoding='utf-8'))
shapes = data['shapes']
        target_label = '1'
        for shape in shapes:
            label = shape['label']
            if label == target_label:
                points = [[float(x[0]), float(x[1])] for x in shape['points']]
                points = np.float32(sort_points(points))

            elif label == '2':
                aim_points = [[float(x[0]), float(x[1])] for x in shape['points']]
                aim_points = np.float32(sort_points(aim_points))

            elif label == '3':
                angle_points = [[float(round(x[0])), float(round(x[1]))] for x in shape['points']]
                angle_points = np.float32(angle_points)

Conversión de dos ángulos

Clasificación de 2.1 puntos

def sort_points_angle(points, meter_number, frame):
    """
    根据角度排序
    """
    meter_number = [0, 0.5, 1, 1.5]
    # print('points:', points)
    center_point = find_center_point(points)
    # print('center point:', center_point)

    other_points = [point for point in points if not np.all(point == center_point)]
    other_points = sort_points_lean(other_points)
    other_points[0], other_points[1] = other_points[1], other_points[0]
    # other_points = [other_points[1], other_points[0], other_points[2], other_points[3]]
    # print('other_points:', other_points)

    angle_lst = []
    for i, point in enumerate(other_points):
        angle = calculate_angle(point, center_point)
        # print('angle:', angle)
        angle_lst.append(angle)

    # print('angle_lst:', angle_lst)
    angle_meter_lst = list(zip(angle_lst, meter_number))
    # print('angle_meter_lst', angle_meter_lst)
    return angle_meter_lst, center_point

2.2 Conversión de ángulo

def calculate_angle(point2, point1):
    # 计算两点之间的角度(以度数为单位)
    angle = np.arctan2(point2[1] - point1[1], point2[0] - point1[0]) * 180 / np.pi
    # print("查看直接识别的角度:", angle)
    if angle < 90:
        angle += 360
    angle -= 90
    return angle

Procesamiento de tres imágenes

def analyze_reading(image, angle_meter_lst, center_point):
    # 转换图像为灰度
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # img_show('gray_image', gray_image)

    # 方图均衡化
    equalized_image = cv2.equalizeHist(gray_image)
    # img_show('equalized_image', equalized_image)

    # 图像取反
    inverted_image = cv2.bitwise_not(equalized_image)
    # img_show('inverted_image', inverted_image)

    # 中值滤波
    median_filtered = cv2.medianBlur(inverted_image, 1)
    # img_show('median_filtered', median_filtered)

    # 腐蚀操作
    kernel = np.ones((5, 5), np.uint8)
    eroded_image = cv2.erode(median_filtered, kernel, iterations=1)
    # img_show('eroded_image', eroded_image)

    # 开运算
    kernel = np.ones((9, 9), np.uint8)
    opening = cv2.morphologyEx(eroded_image, cv2.MORPH_OPEN, kernel)
    # img_show('opening', opening)

    # 二值化
    _, binary_image = cv2.threshold(opening, 150, 255, cv2.THRESH_BINARY)
    # img_show('binary_image', binary_image)

    kernel = np.ones((3, 3), np.uint8)
    binary_image = cv2.erode(binary_image, kernel, iterations=3)
    # img_show('erode_img', binary_image)

    # 细化操作
    # skeletonized_image = cv2.ximgproc.thinning(binary_image)
    # from skimage.morphology import skeletonize
    # skeletonized_image = skeletonize(binary_image)

    meter = detect_point_tradition(image, binary_image, angle_meter_lst, center_point)
    return meter

Cuatro para encontrar el puntero.

def detect_point_tradition(raw_img, resized_image, angle_meter_lst, center_point):
    """ --------------------------------------------- 最传统的方法 ----------------------------------------------"""
    # 进行边缘检测
    edge_img = cv2.Canny(resized_image, threshold1=50, threshold2=150)
    # img_show('edge_img', edge_img)

    # 进行霍夫变换,检测直线
    lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, threshold=50, minLineLength=50, maxLineGap=10)
    # lines = cv2.HoughLines(edge_img, rho=1, theta=np.pi / 180, threshold=100)
    print('检测到的指针数:', len(lines))
    if len(lines) == 0:
        print('\n\n读数失败:', lines)
        return False

    # 找到指针所在的直线
    max_len = 0
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv2.line(raw_img, (x1, y1), (x2, y2), (0, 255, 0), 2)

        # 计算直线长度
        len_line = np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)

        # 找到最长的直线,即指针所在的直线
        if len_line > max_len:
            max_len = len_line
            xy_long = [[x1, y1], [x2, y2], center_point]

    xy_long = [list(map(int, point)) if isinstance(point, np.ndarray) else point for point in xy_long]
    # print('xy_long:', xy_long)
    # 画点
    for point in xy_long:  # src_points
        # 将点的坐标转换为整数
        x, y = map(int, point)

        # 在图像上绘制圆形
        raw_img = cv2.circle(raw_img, (x, y), radius=6, color=(0, 0, 255), thickness=-1)
    cv2.line(raw_img, xy_long[0], xy_long[1], (0, 0, 255), 2)
    # img_show('raw_img', raw_img)

    # 获取指针角度
    angle = calculate_angle(xy_long[0], xy_long[1])

    # 输出指针角度
    meter = transform_angle(angle, angle_meter_lst)
    print(f'指针角度为:{angle}指针读数为:{meter}')

    return meter

Procesamiento posterior:

def transform_angle(angle, angle_meter_lst):
    """
    将角度转换为仪表读数
    [(48.012783124136945, 0), (143.41234750811017, 0.5), (230.5004115580747, 1), (323.13010177980493, 1.6)]
    """
    # angle = 143
    # meter = 0
    print('查看仪表度数区间:', angle_meter_lst)
    for i in range(len(angle_meter_lst) - 1):
        if angle_meter_lst[i][0] < angle < angle_meter_lst[i+1][0]:
            ratio = (angle_meter_lst[i+1][1]-angle_meter_lst[i][1]) / (angle_meter_lst[i+1][0]-angle_meter_lst[i][0])
            meter = angle_meter_lst[i][1] + (angle - angle_meter_lst[i][0]) * ratio
            print('查看斜率和度数:', ratio, meter, '所在区间:', angle_meter_lst[i][0], angle_meter_lst[i + 1][0])
            meter = round(meter, 3)
            return meter
    return False

Puede continuar ajustando el efecto de optimización:

 

Supongo que te gusta

Origin blog.csdn.net/March_A/article/details/132404911
Recomendado
Clasificación