Nanopc T4 使用OpenCV与串口传输

识别长方形: 

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
        }
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值