second commit

This commit is contained in:
uu
2025-07-01 18:06:39 +08:00
parent 36d23e289f
commit a09be3ae69
5 changed files with 1019 additions and 0 deletions

250
CrsLYL02025.py Normal file
View File

@@ -0,0 +1,250 @@
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()