OpenCV入门:计算机视觉中的几何形状与颜色识别技术

计算机视觉中的几何形状与颜色识别技术

任务:先自己在一张白纸上,分别画有矩形三角形圆形,同时给它们内部涂上不同的填充色,你也可以采用电脑绘制这样的图形,并填充色,转到自己手机上。然后 用 python opencv编程,利用笔记本上的摄像头识别出手机画布上的矩形、三角形和圆形,以及它们的颜色,并且把识别的结果用英文文字显示在图形中央位置。
在这里插入图片描述

任务流程

绘制图形和填充颜色:首先,在纸上绘制矩形、三角形和圆形,并填充不同颜色。你可以使用 OpenCV 或其他图形软件在电脑上创建图形,然后通过手机拍照,上传到笔记本。
捕获图像:利用笔记本上的摄像头获取手机屏幕上的图片。我们将通过 OpenCV 来处理这个图片。
图形识别:使用 OpenCV 对捕获的图像进行处理,识别矩形、三角形和圆形。
颜色识别:通过分析每个图形的颜色来确定其填充颜色。
显示识别结果:在识别到的图形上标记它们的名称(矩形、三角形、圆形),并显示其填充颜色。

第一步:采集摄像头图像

背景

需要实时从摄像头获取每一帧图像,作为后续处理的数据来源。

原理

用OpenCV的 cv2.VideoCapture打开摄像头,通过cap.read()循环读取每一帧。

函数原型

cap = cv2.VideoCapture(index[, apiPreference])
ret, frame = cap.read()
cap.release()

参数含义

index:摄像头编号,0为默认。
apiPreference:指定后端API(通常不用,系统自动选择)。

返回值

cv2.VideoCapture:返回摄像头对象。
cap.read():返回(ret, frame),ret为读取状态,frame为当前帧(numpy数组)。

示例代码

cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cap.release()

变量内容

cap:摄像头对象

frame:捕获的当前帧(BGR彩色)

常见问题

  • 读取不到图像(ret为False),常见于摄像头被占用、驱动问题。
  • 外接摄像头需改index为1、2等。

应用场景

实时监控、人脸识别、物体检测

第二步:选取ROI(感兴趣区域/只识别手机屏幕)

背景

为了只检测手机或平板屏幕内的图形,裁剪ROI,避免背景干扰

原理

利用numpy切片,指定矩形区域提取ROI。

函数原型

roi = img[y1:y2, x1:x2]

参数含义

img:输入图像

x1, x2, y1, y2:感兴趣区域左上和右下坐标

返回值

roi:指定的区域,numpy数组

示例代码

y1, y2 = 190, 410
x1, x2 = 250, 650
roi = frame[y1:y2, x1:x2]

变量内容

roi:ROI区域的图像

常见问题

  • 坐标写错会导致裁剪不准,需配合画红框调试。
  • 如果屏幕斜放,可用透视变换(更高级,这里不展开)。

应用场景

指定区域检测,避免背景干扰。

第三步: 图像灰度化

背景

后续二值化轮廓等处理都基于单通道灰度图

原理

cv2.cvtColor把彩色图(BGR)转为灰度图(单通道)。

函数原型

dst = cv2.cvtColor(src, code)

参数含义

src:输入图像
code:颜色空间转换代码,灰度化用cv2.COLOR_BGR2GRAY

返回值

dst:灰度图(单通道)

示例代码

gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)

变量内容

gray:灰度图像(单通道)

常见问题

输入参数错误导致灰度图全黑或全白。

应用场景

二值化、边缘检测、模板匹配等。

第四步:自适应阈值二值化

背景

将灰度图转为黑白(仅0/255),便于后续分割。自适应方式能处理光照不均的情况。

原理

对每个像素,根据其邻域的平均值/高斯加权均值决定阈值。
常用cv2.THRESH_BINARY_INV让形状为白色,背景为黑色,适合找填色形状。

函数原型

dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)

参数含义

src:灰度输入图
maxValue:阈值化后的最大值(通常255)
adaptiveMethod(自适应算法):
  cv2.ADAPTIVE_THRESH_MEAN_C
    含义:对每个像素点,取其周围blockSize大小区域的像素均值,然后减去C作为阈值。
    通俗理解:用邻域平均值减C作为当前点的阈值,适合光照不均匀的场景
    适用:大部分图像、局部对比度大的图形、纸面、屏幕等。
  cv2.ADAPTIVE_THRESH_GAUSSIAN_C
    含义:用高斯加权的邻域均值(就是离当前点越近的像素权重越大)减去C作为阈值。
    适用光线变化特别柔和、有晕影的时候效果更好。
    区别:比MEAN_C更适合有明显阴影或梯度的图像。
thresholdType(阈值类型):
  cv2.THRESH_BINARY
    含义:高于阈值的像素为最大值(如255),否则为0。
    效果:普通黑白分割,物体为白色,背景为黑色。
  cv2.THRESH_BINARY_INV
    含义:高于阈值的像素为0,否则为最大值(如255),黑白反转
    常用场景:大部分OpenCV轮廓检测喜欢物体是白色、背景黑色时选THRESH_BINARY_INV,这样填色图形区域就是白的更好识别。
blockSize:邻域大小(奇数)
C:常数偏移(调阈值)

返回值

dst:二值化结果(0和255)

示例代码

thresh = cv2.adaptiveThreshold(gray, 255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,15, 3)

变量内容

thresh:二值图像(0/255)

常见问题

  • blockSize太小或太大,物体断裂或糊掉。
  • C值太大,细节丢失。

应用场景

纸面拍照、屏幕识别、车牌/票据OCR等。

第五步:轮廓检测

背景

二值化后提取每个独立封闭区域(如圆、三角、矩形等)。

原理

cv2.findContours扫描二值图,返回所有轮廓点。

函数原型

contours, hierarchy = cv2.findContours(image, mode, method)

参数含义

image:二值图(0/255)
mode
  cv2.RETR_EXTERNAL:只检测最外层轮廓
  cv2.RETR_LISTcv2.RETR_TREE:带层级,适合嵌套
method
  cv2.CHAIN_APPROX_SIMPLE:只保存转折点,压缩存储
  v2.CHAIN_APPROX_NONE:保留所有点,精细

返回值

contours:所有轮廓(每个是一个点集)
hierarchy:轮廓层级(本任务用不到)

示例代码

contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

变量内容

contours:每个轮廓是Nx1x2数组(坐标)

常见问题

  • 轮廓数量多杂点多,可加面积筛选。
  • 图形边缘模糊可能导致多个轮廓。

应用场景

物体检测、计数、分割。

第六步:多边形逼近与形状分类

背景

用多边形逼近,将轮廓简化为少量顶点,判断形状(三角形、矩形、圆形等)。

原理

cv2.approxPolyDP根据曲线逼近精度(epsilon)简化轮廓,顶点数=形状类别。

函数原型

approx = cv2.approxPolyDP(curve, epsilon, closed)

参数含义

curve:输入轮廓(点集)
epsilon:逼近精度(一般取0.04 * 周长)
closed:是否闭合(通常True)

返回值

approx:简化后的多边形点集。

示例代码

epsilon = 0.04 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
if len(approx) == 3:
    shape_name = "Triangle"
elif len(approx) == 4:
    shape_name = "Rectangle"
elif len(approx) >= 7:
    shape_name = "Circle"
else:
    continue

变量内容

approx:逼近多边形点集
shape_name:当前形状标签

常见问题

  • epsilon过小:曲线没简化
  • epsilon过大:图形失真
  • 圆形容易判成多边形,需放宽判定条件(顶点数>=7)

应用场景

智能识图、工业检测

第七步:颜色提取与标签化

背景

要把每个图形内部的填充色检测出来。

原理

利用掩模提取图形区域,用cv2.mean算区域平均色,再用HSV区间判断主色

示例代码

mask = np.zeros(gray.shape, dtype=np.uint8)  # 创建了一个和原灰度图(gray)一样大小的二维数组,数据类型是uint8(0~255)
cv2.drawContours(mask, [approx], -1, 255, -1) 
mean_color = cv2.mean(roi, mask=mask)[:3]

def get_color_name(bgr):
    hsv = cv2.cvtColor(np.uint8([[bgr]]), cv2.COLOR_BGR2HSV)[0][0]
    h, s, v = hsv
    if s < 60 and v > 180:
        return "White"
    elif 10 < h < 30:
        return "Yellow"
    elif 90 < h < 130:
        return "Blue"
    elif h < 10 or h > 160:
        return "Red"
    elif 40 < h < 80:
        return "Green"
    else:
        return "Other"

参数含义

cv2.drawContours():OpenCV 用来在图像上画轮廓的函数。
  mask:目标图像,这里是你的掩膜(一般都是全黑的二值图)。
  [approx]:要绘制的轮廓(注意是个列表,里面只有一个轮廓 approx,通常是用cv2.approxPolyDP()得到的)。
  -1:画所有的轮廓。
  255:画笔颜色,这里是255,表示白色(因为掩膜是0~255的灰度图)。
  -1:填充模式,-1 表示把轮廓“内部”填满(不是只画线,是整个区域都涂白)。
cv2.mean(roi, mask=mask)用来算一张图片的“均值”。,
  其中roi可以是你的原图、区域图、或者任何一张三通道/四通道的图片。
  mask=mask 表示只计算掩膜为白色(255)部分的平均值,黑色部分会被忽略。
  如果没有mask,会对整张图做平均。
[:3]
  cv2.mean 的返回值通常是个长度为4的元组,比如 (B, G, R, alpha)。
  但我们通常只关心颜色,不用alpha通道。
  所以取前3个元素,即 (B, G, R)。

返回值

mask:掩模
mean_colortuple,BGR平均值

变量内容

mask:只包含当前图形区域的0/255图像
mean_color:平均色(B, G, R)

常见问题

  • 区域里混入边界,颜色偏差
  • HSV区间需按实际色卡调整

应用场景

色块识别、智能批改、玩具/工业识别

第八步:计算中心点、标注彩色文字、绘制轮廓

背景

把检测结果直观标在图上(彩色文字+描边),方便人理解。

原理

cv2.moments求轮廓质心
cv2.putText写文字,先用黑色粗笔描边再填主色
轮廓点需加上ROI偏移

M = cv2.moments(approx)
cv2.putText(img, text, org, fontFace, fontScale, color, thickness)
cv2.drawContours(img, [approx], -1, color, thickness)

参数含义

img:原图
text:写入内容
org:左下角坐标
fontFace:字体
fontScale:字号
color:BGR颜色
thickness:线宽
approx:当前轮廓
M:几何矩
  从通俗的角度来说,就是用来描述图像形状和区域的一些特性的一种工具。通过计算图像中的“像素”值,我们可以得出一些有用的图像信息,比如图像的中心、面积、形状方向等。可以把它理解为:图像的“统计”信息,它告诉你图像的一些“关键特征”。

返回值

无返回

示例代码

M = cv2.moments(approx)

# 当面积不为0时,重心坐标是 (M["m10"]/M["m00"], M["m01"]/M["m00"])。
if M["m00"] != 0: # M["m00"] 是面积(零阶矩)。

    # M["m10"]、M["m01"] 分别是横、纵方向的“加权和”。
    cX = int(M["m10"] / M["m00"]) 
    cY = int(M["m01"] / M["m00"])

# 如果面积为0(极小或退化成一点),就用approx的第一个顶点作中心。
else:
    cX, cY = approx[0][0]

# 局部坐标(cX, cY)加上偏移量(x1, y1),转换到原图(全局)坐标
cX_global = cX + x1
cY_global = cY + y1
approx_global = approx + [x1, y1]
text = f"{shape_name}, {color_label}"
text_color = tuple([int(x) for x in mean_color])
cv2.putText(frame, text, (cX_global-60, cY_global), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,0,0), 4, cv2.LINE_AA)
cv2.putText(frame, text, (cX_global-60, cY_global), cv2.FONT_HERSHEY_SIMPLEX, 0.9, text_color, 2, cv2.LINE_AA)
cv2.drawContours(frame, [approx_global], -1, text_color, 2)

变量内容

cX_global, cY_global:全图中的中心
text_color:BGR

常见问题

  • 亮色文字不易看,加黑色描边
  • 文字坐标可能出框,微调-60等偏移量

应用场景

自动可视化检测结果

第九步:绘制ROI框、显示窗口

背景

调试ROI区域,方便校准。

原理

cv2.rectangle画红框,cv2.imshow弹出窗口。

函数原型

cv2.rectangle(img, pt1, pt2, color, thickness)
cv2.imshow(winname, mat)

参数含义

img:原图
pt1/pt2:左上/右下点
color:BGR
thickness:线宽
winname:窗口名

返回值

示例代码

cv2.rectangle(frame, (x1, y1), (x2, y2), (0,0,255), 2)
cv2.imshow('Only ROI Detect', frame)

变量内容

常见问题

框画错,需微调坐标

应用场景

检测调试、指定区域作业

第十步:退出与资源释放

背景

程序要有友好的退出方式,释放摄像头和窗口。

原理

v2.waitKey监听按键,cap.release()释放,cv2.destroyAllWindows()关闭窗口。

函数原型

cv2.waitKey(delay)
cap.release()
cv2.destroyAllWindows()

参数含义

delay:等待毫秒数,1表示每帧
cap.release():释放摄像头资源
cv2.destroyAllWindows():关闭所有OpenCV窗口

返回值

示例代码

if cv2.waitKey(1) & 0xFF == ord('q'):
    break
cap.release()
cv2.destroyAllWindows()

变量内容

常见问题

不释放会占用摄像头

应用场景

所有OpenCV交互型脚本

完整代码

import cv2
import numpy as np

def get_color_name(bgr):
    hsv = cv2.cvtColor(np.uint8([[bgr]]), cv2.COLOR_BGR2HSV)[0][0]
    h, s, v = hsv
    if s < 60 and v > 180:
        return "White"
    elif 10 < h < 30:
        return "Yellow"
    elif 90 < h < 130:
        return "Blue"
    elif h < 10 or h > 160:
        return "Red"
    elif 40 < h < 80:
        return "Green"
    else:
        return "Other"

cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    if not ret:
        break

    # ROI选屏幕区域
    y1, y2 = 190, 410
    x1, x2 = 250, 650
    roi = frame[y1:y2, x1:x2]

    # 灰度化
    gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
    # 自适应阈值二值化
    thresh = cv2.adaptiveThreshold(
        gray, 255,
        cv2.ADAPTIVE_THRESH_MEAN_C,
        cv2.THRESH_BINARY_INV,
        15, 3
    )

    # 轮廓检测
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    for contour in contours:
        area = cv2.contourArea(contour) # 计算当前轮廓的面积
        if area < 800 or area > 80000:
            continue # 跳过当前的轮廓,进入下一个轮廓的处理

        epsilon = 0.04 * cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, epsilon, True)

        if len(approx) == 3:
            shape_name = "Triangle"
        elif len(approx) == 4:
            shape_name = "Rectangle"
        elif len(approx) >= 7:
            shape_name = "Circle"
        else:
            continue

        mask = np.zeros(gray.shape, dtype=np.uint8)
        cv2.drawContours(mask, [approx], -1, 255, -1)
        mean_color = cv2.mean(roi, mask=mask)[:3]
        color_label = get_color_name(mean_color)

        M = cv2.moments(approx)
        # 当面积不为0时,重心坐标是 (M["m10"]/M["m00"], M["m01"]/M["m00"])。
        if M["m00"] != 0: # M["m00"] 是面积(零阶矩)。

            # M["m10"]、M["m01"] 分别是横、纵方向的“加权和”。
            cX = int(M["m10"] / M["m00"]) 
            cY = int(M["m01"] / M["m00"])

        # 如果面积为0(极小或退化成一点),就用approx的第一个顶点作中心。
        else:
            cX, cY = approx[0][0]

        # 局部坐标(cX, cY)加上偏移量(x1, y1),转换到原图(全局)坐标
        cX_global = cX + x1
        cY_global = cY + y1
        approx_global = approx + [x1, y1]
        text = f"{shape_name}, {color_label}"
        text_color = tuple([int(x) for x in mean_color]) # 浮动类型的列表或元组转换为一个包含整数的元组,用于表示颜色值
        cv2.putText(frame, text, (cX_global-60, cY_global), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,0,0), 4, cv2.LINE_AA) # 图像的指定位置绘制黑色的文字
        cv2.putText(frame, text, (cX_global-60, cY_global), cv2.FONT_HERSHEY_SIMPLEX, 0.9, text_color, 2, cv2.LINE_AA)
        cv2.drawContours(frame, [approx_global], -1, text_color, 2)

    cv2.rectangle(frame, (x1, y1), (x2, y2), (0,0,255), 2)
    cv2.imshow('Only ROI Detect', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
在这里插入图片描述

cap.release()
cv2.destroyAllWindows()

在这里插入图片描述

<think>嗯,用户想了解RV1103相机的调试。首先,我需要确定RV1103是什么芯片。RV1103是瑞芯微推出的低功耗视觉处理器,常用于智能摄像头、物联网设备。调试相机模块可能涉及硬件连接、软件配置、驱动调试等方面。 用户可能是工程师或开发者,遇到相机模块无法正常工作的问题,需要指导调试步骤。深层需求可能是解决图像不显示、图像质量差或性能优化等问题。 首先,硬件检查是关键。确保电源稳定,接口正确连接,比如MIPI CSI-2接口是否正确。时钟和数据线是否匹配,避免信号干扰。可能需要检查硬件设计是否符合规格,比如电压、阻抗匹配。 然后是软件部分,需要配置设备树(DTS),正确描述相机模块的参数,比如时钟频率、分辨率、I2C地址。驱动是否正常加载,内核日志(dmesg)是否有错误信息。可能需要调试V4L2框架,确保应用层能正确获取图像数据。 图像质量调试,比如调整曝光、白平衡、色彩校正。使用工具如v4l2-ctl来设置参数,或通过ISP(图像信号处理器)进行调优。还可能涉及固件更新,确保传感器和主控的兼容性。 此外,调试工具和方法,如使用示波器检查信号完整性,逻辑分析仪抓取MIPI数据。软件层面,可能需要修改内核驱动,调试寄存器配置,或传感器厂商合作获取支持。 需要注意RV1103的具体文档和SDK,不同厂商的传感器配置可能不同。用户可能需要查阅瑞芯微的官方资料,参考示例配置,逐步排查问题。如果有具体问题,比如某个错误日志,可以更针对性地解决。</think>RV1103 是瑞芯微(Rockchip)推出的一款低功耗视觉处理芯片,主要用于智能摄像头、IoT视觉终端等场景。其相机调试涉及硬件接口、驱动配置、图像处理等多个环节,以下是关键调试步骤的概述: --- ### **一、硬件调试基础** 1. **接口确认** - **MIPI CSI-2**:检查摄像头模组RV1103的MIPI接口(CLK+/CLK-, DATA+/DATA-)物理连接,确保阻抗匹配(差分线100Ω)。 - **I2C控制**:确认摄像头I2C地址驱动配置一致(通常为0x3C或0x3D)。 - **电源时钟**:测量摄像头供电(如1.8V/2.8V)是否稳定,MCLK(主时钟)频率是否匹配(例如24MHz)。 2. **信号完整性** - 使用示波器检查MIPI信号的眼图质量,避免因走线过长或干扰导致数据丢包。 - 验证同步信号(VSYNC/HSYNC)是否正常触发。 --- ### **二、软件驱动配置** 1. **设备树(DTS)配置** - 在Linux内核设备树中定义摄像头节点,例如: ```dts &csi_dphy { status = "okay"; }; &mipi_csi2 { status = "okay"; ports { port@0 { mipi_csi2_input: endpoint { remote-endpoint = <&ov5647_out>; data-lanes = <1 2>; // 根据实际摄像头MIPI通道数配置 }; }; }; }; &i2c1 { status = "okay"; ov5647: camera@36 { compatible = "ovti,ov5647"; reg = <0x36>; clocks = <&cru CLK_MIPICSI_OUT>; pwdn-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; // 其他参数:分辨率、帧率等 }; }; ``` 2. **驱动加载验证** - 通过`dmesg | grep csi`检查内核日志,确认CSI和摄像头驱动是否成功加载。 - 使用`v4l2-ctl --list-devices`查看摄像头设备是否注册。 --- ### **三、图像调试工具** 1. **V4L2工具链** - 抓图测试:`v4l2-ctl --device /dev/video0 --stream-mmap --stream-to=test.raw` - 格式转换:通过`ffmpeg`将RAW数据转为可查看的格式(如YUV420P)。 2. **ISP调优** - 通过瑞芯微提供的`rkisp_3A_server`工具调整曝光、白平衡、降噪等参数。 - 修改`/etc/iq_files/`下的IQ配置文件(如`ov5647.xml`)优化图像效果。 --- ### **四、常见问题排查** 1. **无图像输出** - 检查供电和MCLK是否正常。 - 确认I2C通信成功:`i2cdetect -y 1`扫描设备地址。 - 内核日志中是否有`mipi_dphy`或`v4l2`相关报错。 2. **图像花屏/撕裂** - 调整MIPI时序参数(如`lane_rate`、`csi_dphy_clk`)。 - 检查DDR带宽是否不足(降低分辨率或帧率测试)。 --- ### **五、参考资料** 1. 瑞芯微官方文档:《RV1103 Linux SDK开发指南》 2. 摄像头Sensor Datasheet(如OV5647、GC2053等) 3. Linux V4L2框架文档:https://www.kernel.org/doc/html/latest/userspace-api/media/index.html 如果需要进一步分析具体问题(如寄存器配置、图像效果调优),建议提供硬件设计原理图或内核日志错误片段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值