识别长方形:
import cv2
import cv2 as cv
import time
import platform
import os
# 获取操作系统类型
os_type = platform.system()
if os_type == "Windows":
# Windows系统
cap = cv.VideoCapture(0) # 使用第零个摄像头
elif os_type == "Linux":
# Linux系统
cap = cv.VideoCapture(10) # 使用第十个摄像头
if not cap.isOpened():
print("Cannot capture from camera. Exiting.")
os._exit(1) # 退出程序
last_time = time.time()
while (True):
ret, frame = cap.read()
imgContour = frame.copy()
imgCanny = cv2.Canny(frame, 60, 60) # Canny算子边缘检测
contours, hierarchy = cv2.findContours(imgCanny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 寻找轮廓点
for obj in contours:
area = cv2.contourArea(obj) # 计算轮廓内区域的面积
# cv2.drawContours(imgContour, obj, -1, (255, 0, 0), 4) # 绘制轮廓线
perimeter = cv2.arcLength(obj, True) # 计算轮廓周长
approx = cv2.approxPolyDP(obj, 0.02 * perimeter, True) # 获取轮廓角点坐标
CornerNum = len(approx) # 轮廓角点的数量
x, y, w, h = cv2.boundingRect(approx) # 获取坐标值和宽度、高度
if CornerNum == 4:
if 90 < w != h > 50:
objType = "ChangFangXing"
cv2.rectangle(imgContour, (x, y), (x + w, y + h), (0, 0, 255), 2) # 绘制边界框
cv2.putText(imgContour, objType, (x + (w // 2), y + (h // 2)), cv2.FONT_HERSHEY_COMPLEX, 0.6, (0, 0, 0),
1) # 绘制文字
cv2.imshow("shape Detection", imgContour)
if cv.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()
识别人脸1:
import cv2
import cv2 as cv
import time
import platform
import os
# 获取操作系统类型
os_type = platform.system()
if os_type == "Windows":
# Windows系统
cap = cv.VideoCapture(0) # 使用第零个摄像头
elif os_type == "Linux":
# Linux系统
cap = cv.VideoCapture(10) # 使用第十个摄像头
if not cap.isOpened():
print("Cannot capture from camera. Exiting.")
os._exit(1) # 退出程序
last_time = time.time()
img = cv.imread("D:\WorkSpace\Python\qsc.png")
def template_matching(img_match, img, arithmetic_model):
'''
【作用】
进行图片模板匹配
【参数1】
模板图片
【参数2】
进行匹配的图片
【参数3】
算法模型
【返回】
无
'''
# 进行模板匹配
result = cv.matchTemplate(img, img_match, arithmetic_model)
# 获取最小最大匹配值,还有对应的坐标
min_value, max_value, min_coordinate, max_coordinate = cv.minMaxLoc(result)
# 默认最佳最大值,当算法为CV_TM_SQDIFF或CV_TM_SQDIFF_NORMED时改为最小值
best_coordinate = max_coordinate
if arithmetic_model == cv.TM_SQDIFF or arithmetic_model == cv.TM_SQDIFF_NORMED:
best_coordinate = min_coordinate
# 获取匹配图片的高和宽
m_height, m_width = img_match.shape[:2]
# 矩形的起始点和结束点
r_start = best_coordinate
r_end = (best_coordinate[0] + m_width, best_coordinate[1] + m_height);
# 矩形的颜色和线的宽度
r_color = (0, 100, 40)
r_line_width = 2
# 绘制矩形并展示
cv.rectangle(img, r_start, r_end, r_color, r_line_width)
cv.imshow("Qu ShiChao", img)
while (True):
ret, frame = cap.read()
template_matching(img, frame, cv.TM_SQDIFF)
if cv.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()
通模型识别人脸
import cv2
import cv2 as cv
import time
import platform
import os
# 获取操作系统类型
os_type = platform.system()
if os_type == "Windows":
# Windows系统
cap = cv.VideoCapture(0) # 使用第零个摄像头
elif os_type == "Linux":
# Linux系统
cap = cv.VideoCapture(10) # 使用第十个摄像头
if not cap.isOpened():
print("Cannot capture from camera. Exiting.")
os._exit(1) # 退出程序
last_time = time.time()
while (True):
ret, frame = cap.read()
# 这里是你的xml存放路径
face_cascade = cv2.CascadeClassifier("D:\WorkSpace\Python\lbpcascade_frontalface.xml")
# 开始人脸检测
faces = face_cascade.detectMultiScale(frame, scaleFactor=1.03, minNeighbors=6)
# 先复制一张图片
frame1 = frame.copy()
# 在检测到的人脸中操作
for x, y, w, h in faces:
# 画出人脸框
frame1 = cv2.rectangle(frame1, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 找出人脸区域
face_area = frame1[y:y + h, x:x + w]
# 在人脸区域检测人眼
cv2.imshow('face', frame1)
if cv.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()
识别电赛E题目
import collections
import cv2 as cv
import cv2
import numpy as np
import platform
CameraDriverNumber = 0 # 根据系统切换设备号
# 获取操作系统类型
os_type = platform.system()
if os_type == "Linux": # Linux系统
CameraDriverNumber = 10
cap = cv.VideoCapture(CameraDriverNumber) # 使用第十个摄像头
ret, image = cap.read() # 打印图片像素大小
size = image.shape
# print(f"Pixel W:{size[1]} H:{size[0]} ")
limit_Mini_X = limit_Mini_Y = 480
limit_Max_X = limit_Max_Y = 0
PenMax_rect_points = cv.boxPoints(((0, 0), (0, 0), 0)).astype(int) # 外铅笔框坐标
PenMin_rect_points = cv.boxPoints(((0, 0), (0, 0), 0)).astype(int) # 外铅笔框坐标
outside_rect_points = cv.boxPoints(((0, 0), (0, 0), 0)).astype(int) # A4纸外坐标
inside_rect_points = cv.boxPoints(((0, 0), (0, 0), 0)).astype(int) # A4纸内坐标
A4_Points = [[0, 0], [0, 0], [0, 0], [0, 0]]
Pen_Points = np.float32([[0, 0], [0, 0], [0, 0], [0, 0]])
OutPut_Points = [[0, 0], [0, 0], [0, 0], [0, 0]]
last_X = [0, 0, 0, 0, 0]
last_Y = [0, 0, 0, 0, 0]
# Initialize buffers for storing the previous points
pen_point0_buffer = collections.deque(maxlen=5) # Buffer with maxlen 5 for smoothing
pen_point1_buffer = collections.deque(maxlen=5) # Buffer with maxlen 5 for smoothing
pen_point2_buffer = collections.deque(maxlen=5) # Buffer with maxlen 5 for smoothing
pen_point3_buffer = collections.deque(maxlen=5) # Buffer with maxlen 5 for smoothing
A4_point0_buffer = collections.deque(maxlen=5) # Buffer with maxlen 5 for smoothing
A4_point1_buffer = collections.deque(maxlen=5) # Buffer with maxlen 5 for smoothing
A4_point2_buffer = collections.deque(maxlen=5) # Buffer with maxlen 5 for smoothing
A4_point3_buffer = collections.deque(maxlen=5) # Buffer with maxlen 5 for smoothing
# 连接串口
# com = serial.Serial('COM22', 115200)
'''
def UsartSend(send_data):
if com.isOpen():
com.write(send_data.encode('utf-8')) # 编码
# print("发送成功", send_data)
else:
print("发送失败!")
'''
def transform_point(point, perspective_matrix):
"""
将输入点通过透视变换矩阵转换到新坐标系
参数:
point (tuple): 输入点的坐标 (x, y)
perspective_matrix (numpy.ndarray): 3x3 透视变换矩阵
返回:
numpy.ndarray: 变换后的点的坐标 (x', y')
"""
# 将点扩展为齐次坐标
point_in_original = np.array([point[0], point[1], 1.0], dtype=np.float32)
# 通过透视变换矩阵变换点
transformed_point = perspective_matrix.dot(point_in_original)
# 转换为非齐次坐标
transformed_point /= transformed_point[2]
return transformed_point[:2]
def smooth_point(new_point, buffer):
"""
Apply moving average to smooth the points.
参数:
new_point (tuple): 新的点坐标 (x, y)
buffer (collections.deque): 存储之前点坐标的缓冲区
返回:
tuple: 平滑后的点坐标 (x, y)
"""
if len(buffer) == 0:
# If buffer is empty, initialize with the first point
buffer.extend([new_point] * buffer.maxlen)
else:
buffer.append(new_point)
smoothed_point = np.mean(buffer, axis=0)
return smoothed_point
while True:
# 读取图像帧
ret, frame = cap.read()
# cv.imshow('frame', frame)
frame = frame[0:480, 75:555] # ROI Y轴以左上角为起点,左下角为终点 X轴以左上角为起点,右上角为终点
size = frame.shape # 将左上角切换以左下角为原点
frame1 = frame.copy()
# 将图像转换为灰度图像
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# cv.imshow('gray', gray)
# Canny算子边缘检测
imgCanny = cv2.Canny(gray, 60, 60)
# cv.imshow('imgCanny', imgCanny)
# 检测轮廓
ret, binary = cv.threshold(imgCanny, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
# cv.imshow('c', binary)
# 膨胀操作
mask = np.zeros((size[0], size[1]), dtype=np.uint8) # 创建一个与图像大小相同的全黑掩码
k2 = np.ones((15, 15), np.uint8)
mask[int(limit_Mini_Y + 2):int(limit_Max_Y - 2), int(limit_Mini_X + 2):int(limit_Max_X - 2)] = 255 # 将保护区域设置为白色
inverse_mask = cv2.bitwise_not(mask) # 对掩码取反,得到非保护区域
non_protected_area = cv2.bitwise_and(binary, inverse_mask) # 将非保护区域提取出来
kernel = np.ones((3, 3), np.uint8) # 创建一个膨胀核
dilated_area = cv2.dilate(non_protected_area, kernel, iterations=1)
# 将膨胀处理后的区域与原图像的保护区域合并
protected_area = cv2.bitwise_and(binary, mask)
# cv.imshow('closing', protected_area)
binary2 = cv2.bitwise_or(dilated_area, protected_area)
cv.imshow('binary2', binary2)
# 执行轮廓检测
contours, _ = cv.findContours(binary2, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
# 初始化最小面积和对应的轮廓索引
# 初始化最小面积和对应的轮廓索引
A4_min_area = float('inf') # 正无穷
A4_max_area = float('-inf') # 负无穷
Pen_max_area = float('-inf') # 负无穷
Pen_min_area = float('inf') # 正无穷
A4_outside_index = -1
A4_inside_index = -1
Pen_outside_index = -1
Pen_inside_index = -1
for i, contour in enumerate(contours): # 遍历所有轮廓
# 进行矩形拟合
rect = cv.minAreaRect(contour) # 最小包围矩形及其面积
epsilon = 0.05 * cv.arcLength(contour, True)
approx = cv.approxPolyDP(contour, epsilon, True)
# 计算轮廓面积
area = cv.contourArea(contour)
# cv.drawContours(frame, [cv.boxPoints(rect).astype(int)], 0, (0, 25, 0), 2)
if rect[1][1] > 5 and rect[1][0] > 5:
Scal = rect[1][1] / rect[1][0] # A4纸尺寸 210mm×297mm 297mm/210mm=1.414285714285714
if 1.5 > Scal > 1.3 and len(approx) == 4: # 外
if area > A4_max_area:
A4_max_area = area
A4_outside_index = i
outside_rect_points = cv.boxPoints(rect).astype(int)
# print(f"{rect[1][0]} {rect[1][1]} {Scal}") # 打印识别的 宽 高 比例
# cv.drawContours(frame, [outside_rect_points], 0, (0, 255, 0), 2)
if area < A4_min_area and area < A4_max_area: # 内
A4_min_area = area
A4_inside_index = i
inside_rect_points = cv.boxPoints(rect).astype(int)
# print(f"{rect[1][0]} {rect[1][1]} {Scal}") # 打印识别的 宽 高 比例
# cv.drawContours(frame, [inside_rect_points], 0, (0, 255, 0), 2)
if 0.9 < Scal < 1.2 and 15 > len(approx) >= 4 and rect[1][0] > 100:
if area > Pen_max_area:
Pen_max_area = area
Pen_outside_index = i
PenMax_rect_points = cv.boxPoints(rect).astype(int)
if area < Pen_min_area:
Pen_min_area = area
Pen_inside_index = i
PenMin_rect_points = cv.boxPoints(rect).astype(int)
limit_Mini_X = limit_Mini_Y = 480
limit_Max_X = limit_Max_Y = 0
if A4_inside_index != -1 and A4_outside_index != -1:
for index, (pointOut, pointIn) in enumerate(zip(outside_rect_points, inside_rect_points)): # 处理识别到的三个矩形
# A4纸
diff_x = abs(pointOut[0] - pointIn[0])
diff_y = abs(pointOut[1] - pointIn[1])
if 50 >= diff_x >= 0 and 50 >= diff_y >= 0:
limit_Max_X = pointOut[0] if pointOut[0] > limit_Max_X else limit_Max_X # 求四周限幅值
limit_Max_Y = pointOut[1] if pointOut[1] > limit_Max_Y else limit_Max_Y
limit_Mini_X = pointOut[0] if pointOut[0] < limit_Mini_X else limit_Mini_X
limit_Mini_Y = pointOut[1] if pointOut[1] < limit_Mini_Y else limit_Mini_Y
mid_x = (pointIn[0] + pointOut[0]) / 2 # 计算中间值
mid_y = (pointIn[1] + pointOut[1]) / 2
if index == 0:
smoothed_point = smooth_point((mid_x, mid_y), A4_point0_buffer)
mid_x, mid_y = smoothed_point
if index == 1:
smoothed_point = smooth_point((mid_x, mid_y), A4_point1_buffer)
mid_x, mid_y = smoothed_point
if index == 2:
smoothed_point = smooth_point((mid_x, mid_y), A4_point2_buffer)
mid_x, mid_y = smoothed_point
if index == 3:
smoothed_point = smooth_point((mid_x, mid_y), A4_point3_buffer)
mid_x, mid_y = smoothed_point
# print(f"diff_x={diff_x} diff_y={diff_y}") # 打印识别的 宽 高 比例
cv.drawContours(frame, [inside_rect_points], 0, (0, 255, 0), 2)
cv.drawContours(frame, [outside_rect_points], 0, (0, 255, 0), 2)
cv.circle(frame, (int(mid_x), int(mid_y)), 5, (0, 0, 255), -1)
# temp_mid_y = size[0] - mid_y
A4_Points[index] = [mid_x, mid_y]
cv.putText(frame, f"{index}:({mid_x}-{mid_y})", tuple((int(mid_x), int(mid_y))),
cv.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 1)
if Pen_outside_index != -1 and Pen_inside_index != -1:
for index, (pointPenOut, pointPenIn) in enumerate(zip(PenMax_rect_points, PenMin_rect_points)):
# print(f"{index + 1} {abs(pointPenOut[0] - pointPenIn[0])} {abs(pointPenOut[1] - pointPenIn[1])}")
if abs(pointPenOut[0] - pointPenIn[0]) < 50 and abs(pointPenOut[1] - pointPenIn[1]) < 50:
temp_X = (pointPenOut[0] + pointPenIn[0]) / 2
temp_Y = (pointPenOut[1] + pointPenIn[1]) / 2
num = 0
if temp_X > size[1] / 2: # 右侧
temp_X = temp_X - 6
if temp_Y > size[0] / 2: # 上
temp_Y = temp_Y - 6
# Smooth the points
smoothed_point = smooth_point((temp_X, temp_Y), pen_point3_buffer)
temp3_X, temp3_Y = smoothed_point
Pen_Points[3] = [temp3_X, temp3_Y]
num = 3
else:
temp_Y = temp_Y + 6
# Smooth the points
smoothed_point = smooth_point((temp_X, temp_Y), pen_point2_buffer)
temp2_X, temp2_Y = smoothed_point
Pen_Points[2] = [temp2_X, temp2_Y]
num = 2
else: # 左侧
temp_X = temp_X + 6
if temp_Y > size[0] / 2: # 上
temp_Y = temp_Y - 6
# Smooth the points
smoothed_point = smooth_point((temp_X, temp_Y), pen_point0_buffer)
temp0_X, temp0_Y = smoothed_point
Pen_Points[0] = [temp0_X, temp0_Y]
num = 0
else: # 下
temp_Y = temp_Y + 6
# Smooth the points
smoothed_point = smooth_point((temp_X, temp_Y), pen_point1_buffer)
temp1_X, temp1_Y = smoothed_point
Pen_Points[1] = [temp1_X, temp1_Y]
num = 1
cv.putText(frame, f"{num}:({int(Pen_Points[num][1])}-{int(Pen_Points[num][0])})",
tuple((int(Pen_Points[num][1]), int(Pen_Points[num][0]))),
cv.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 1)
cv.circle(frame, (int(Pen_Points[num][1]), int(Pen_Points[num][0])), 5, (0, 255, 0), -1) # 铅笔框四角的红点
# print(f"{index + 1} {temp_X} {temp_Y}") # 打印识别的 宽 高 比例
# cv.drawContours(frame, [Pen_rect_points], 0, (0, 255, 0), 2) # 铅笔框
# 根据四个顶点计算图像 透视变换(Perspective Transform)
target_points = np.float32([
[0, 0], # Point 1
[0, 500], # Point 2
[500, 500], # Point 3
[500, 0] # Point 4
])
perspective_matrix = cv2.getPerspectiveTransform(Pen_Points, target_points) # 原始坐标 目标坐标
# 应用透视变换
output_image = cv.warpPerspective(frame1, perspective_matrix, (500, 500))
output_image = cv2.flip(output_image, 0) # 翻转
# 使用封装的函数进行点的透视变换
output_size = output_image.shape # 将左上角切换以左下角为原点
for i in range(0, 4):
OutPut_Points[i] = transform_point(A4_Points[i], perspective_matrix)
cv.circle(output_image, (int(OutPut_Points[i][0]), output_size[0] - int(OutPut_Points[i][1])), 5, (0, 255, 0),
-1) # 铅笔框四角的红点
cv.putText(output_image, f"{i}:({int(OutPut_Points[i][0])}-{int(OutPut_Points[i][1])})",
tuple((int(OutPut_Points[i][0]), output_size[0] - int(OutPut_Points[i][1]))),
cv.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 1)
cv.imshow('Transformed Image', output_image)
cv.imshow("result", frame)
# 按下Esc键退出
if cv.waitKey(1) == 27:
break
# 关闭摄像头
cap.release()
cv.destroyAllWindows()
串口使用:
命令行查看串口she'b
ls /dev/ttyS*
/dev/ttyS0 /dev/ttyS4
ttyS4 为GPIO的串口
使用CuteCom检查串口
这个就友好点,有界面了。和Windows的差不多,可以选择串口,设置波特率、数据位、停止位等。
# 安装
sudo apt install cutecom
# 启动
sudo cutecom
#include <wiringPi.h>
#include <wiringSerial.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
int main() {
int filedevid;
int recbytenum;
int i;
char buf[1024];
memset(buf, 0, sizeof(buf));
if (wiringPiSetup() == -1) {
printf("wiringPi setup failed\r\n");
return -1;
}
if ((filedevid = serialOpen("/dev/ttyS4", 115200)) < 0) {
perror("/dev/ttyS4 Open Failed");
return -1;
} else {
printf("/dev/ttyS4 Open with 115200, success\r\n");
while (1) {
recbytenum = serialDataAvail(filedevid);
if (recbytenum > 0) {
i = 0;
while (recbytenum-- && i < sizeof(buf) - 1) {
buf[i++] = serialGetchar(filedevid);
}
buf[i] = '\0'; // Ensure the buffer is null-terminated
printf("Rpi uart recv: %s\r\n", buf);
// Echo back received data
serialPrintf(filedevid, "Rpi uart send: %s\r\n", buf);
memset(buf, 0, sizeof(buf));
}
// Send some data periodically
serialPrintf(filedevid, "Hello from Raspberry Pi!\r\n");
delay(1000); // Wait for 1 second before sending again
}
}
}