Files
backend/CrsLYL02025.py
2025-07-01 18:06:39 +08:00

250 lines
8.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import os
import numpy as np
import cv2
import time
def set_camera_resolution(cap, width, height):
"""
设置摄像头的分辨率。
参数:
- cap: cv2.VideoCapture 对象
- width: 目标宽度
- height: 目标高度
"""
# 设置摄像头的宽度和高度
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
# 获取实际设置的宽度和高度
actual_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
actual_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
print(f"设置的分辨率: 宽度={width}, 高度={height}")
print(f"实际的分辨率: 宽度={actual_width}, 高度={actual_height}")
def show_mask(mask, ax, random_color=False):
if random_color:
color = np.concatenate([np.random.random(3), np.array([0.6])], axis=0)
else:
color = np.array([30/255, 144/255, 255/255, 0.6])
h, w = mask.shape[-2:]
mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1)
ax.imshow(mask_image)
def findchesslen(image):
# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 棋盘格规格例如8x8内部角点根据你的实际棋盘规格修改
board_size = (3, 4) # 对于8x8的棋盘内部角点数为7x7
ret, corners = cv2.findChessboardCorners(gray, board_size, None)
frameshow = image.copy()
cv2.drawChessboardCorners(frameshow, board_size, corners, ret)
cv2.imshow('Chessboard Corners', frameshow)
if ret: # 如果成功找到角点
distances = []
for row in range(board_size[1]): # 遍历每一行
for col in range(board_size[0] - 1): # 对于每行中的每个角点,计算到下一个角点的距离
idx = row * board_size[0] + col
p1 = corners[idx][0]
p2 = corners[idx + 1][0]
distance = np.linalg.norm(p1 - p2)
distances.append(distance)
print(f"角点 {idx}{idx+1} 的距离: {distance:.2f} 像素")
for col in range(board_size[0]): # 遍历每一列
for row in range(board_size[1] - 1): # 对于每列中的每个角点,计算到下一个角点的距离
idx = row * board_size[0] + col
p1 = corners[idx][0]
p2 = corners[idx + board_size[0]][0]
distance = np.linalg.norm(p1 - p2)
distances.append(distance)
print(f"角点 {idx}{idx+board_size[0]} 的距离: {distance:.2f} 像素")
# 计算平均边长
avg_distance = np.mean(distances)
return avg_distance
else:
return -1
def getseeds(image,dislen=89.01):
frame = image
# 将图像从BGR转换为HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 定义橘红色在HSV颜色空间中的范围
# 色调(H)橘红色大致在0-20之间
# 饱和度(S):通常较高的值表示更纯的颜色
# 亮度(V):根据具体需求调整,这里我们选择较低的阈值以包含较暗的部分
lower_orange_red = np.array([0, 180, 80])
upper_orange_red = np.array([30, 255, 195])
# 创建掩码
mask = cv2.inRange(hsv, lower_orange_red, upper_orange_red)
# 找到符合条件的像素坐标
orange_red_points = cv2.findNonZero(mask)
frameshow = frame.copy()
# 创建一个与原图大小相同的空白掩码
mask = np.zeros_like(frame[:, :, 0]) # 单通道掩码
if orange_red_points is not None:
for point in orange_red_points:
x, y = point[0]
# 在原图上画圆标记这些点
cv2.circle(frameshow, (x, y), 1, (0, 255, 0), -1) # 使用绿色标记点
cv2.circle(mask, (x, y), 1, 255, -1) # 使用白色标记点
# 查找轮廓
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
for max_contour in contours:
# 找到面积最大的轮廓
# max_contour = max(contours, key=cv2.contourArea)
# 计算最小边界矩形(旋转)
rect = cv2.minAreaRect(max_contour)
box = cv2.boxPoints(rect)
box = np.int32(box)
# 计算边界框的宽度和高度
width = int(rect[1][0])
height = int(rect[1][1])
# 输出边界框的信息
# print(f"Bounding Box Center: ({rect[0][0]:.2f}, {rect[0][1]:.2f})")
# print(f"Bounding Box Width: {width}")
# print(f"Bounding Box Height: {height}")
if dislen >20 and rect[1][0] > 25 and rect[1][1] > 25 :
ww = rect[1][0]*3.0/dislen
hh = rect[1][1]*3.0/dislen
# 格式化输出保留两位有效数字
ww_text = f"w=: {ww:.2f}"
hh_text = f"h=: {hh:.2f}"
# 获取边界框左上角的坐标
# x, y = np.min(box, axis=0)
# 计算中心点
x = int(np.mean(box[:, 0]))
y = int(np.mean(box[:, 1]))
print(x,y)
print(rect[1][0])
print(ww_text)
# center_point = (center_x, center_y)
# 设置字体、缩放比例、颜色和厚度
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 2
color = (0, 0, 255) # BGR颜色格式这里是蓝色
thickness = 2
# 显示宽度信息
cv2.putText(frameshow, ww_text, (x, y-10), font, font_scale, color, thickness)
# 显示高度信息
cv2.putText(frameshow, hh_text, (x, y - 40), font, font_scale, color, thickness)
# 在原图上绘制边界框
cv2.drawContours(frameshow, [box], 0, (0, 0, 255), 2)
# 显示结果帧
# cv2.imshow('Orange Red Points and Bounding Box', frameshow)
return frameshow
# 显示结果帧
#cv2.imshow('Orange Red Points', frameshow)
# 打开USB摄像头
cap = cv2.VideoCapture(0) # 0是默认的摄像头ID如果有多个摄像头可能需要调整
# 设置目标分辨率
target_width = 1920
target_height = 1080
set_camera_resolution(cap, target_width, target_height)
if not cap.isOpened():
print("无法打开摄像头")
else:
last_save_time = time.time()
interval = 10*20 # 10分钟间隔
save_dir="data"
save_path_format="frame_%m-%d_%H-%M.png"
save_path_format_det="frame_%m-%d_%H-%M_det.png"
if not os.path.exists(save_dir):
os.makedirs(save_dir)
# 设置显示窗口的目标尺寸
display_width = 640
display_height = 360
while True:
ret, frame = cap.read()
## height, width, channels = frame.shape[:3] # 获取帧的高度、宽度和通道数
#print(f"Frame 尺寸: 宽度={width}, 高度={height}, 通道数={channels if len(frame.shape) == 3 else 1}")
if not ret:
print("无法获取帧")
break
if 0:
#print(frame)
dislen = findchesslen(frame)
#dislen = 148.50
print(f"cell={dislen}")
cv2.waitKey(20)
continue
#continue
#print(frame)
#dislen = findchesslen(frame)
dislen = 147.50
#print(f"cell={dislen}")
# frame_det = frame
frame_det = getseeds(frame,dislen)
rzframe = cv2.resize(frame, (display_width, display_height))
cv2.imshow('orgimage', rzframe)
rzframe_det = cv2.resize(frame_det, (display_width, display_height))
cv2.imshow('detimage', rzframe_det)
current_time = time.time()
if current_time - last_save_time > interval:
# 根据当前时间生成文件名
file_name = time.strftime(save_path_format, time.localtime(current_time))
file_name_det = time.strftime(save_path_format_det, time.localtime(current_time))
save_path = os.path.join(save_dir, file_name)
save_path_det = os.path.join(save_dir, file_name_det)
# 保存原始帧
cv2.imwrite(save_path, frame)
print(f"已保存帧到 {save_path}")
# 获取并保存检测结果帧
cv2.imwrite(save_path_det, frame_det)
print(f"已保存检测结果帧到 {save_path_det}")
last_save_time = current_time # 更新最后保存时间为当前时间
# 显示结果帧
# cv2.imshow('Chessboard Corners', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()