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: