Opencv(Open Source Computer Vision Library)是一个基于开源发行的跨平台计算机视觉库,它实现了图像处理和计算机视觉方面的很多通用算法,已成为计算机视觉领域最有力的研究工具。在深度学习中,我们会经常接触到两个名称,图像处理和计算机视觉,它们之间有什么区别呢?
图像处理 (Image Processing)
计算机视觉 (Computer Vision)
简而言之,图像处理是计算机视觉的基础,提供了必要的工具和技术来预处理和优化图像数据;而计算机视觉则是在此基础之上,通过更加复杂的算法和模型来解析图像的意义。
在实际应用中,这两者往往是紧密结合的,共同作用于解决复杂的问题。例如,在一个自动驾驶系统中,图像处理可能会用于清理传感器输入的数据,而计算机视觉则负责识别道路上的行人、车辆和其他重要元素。
OpenCV 是一个开源的计算机视觉和机器学习软件库,广泛用于图像处理、视频捕捉、物体检测等领域。一些常用操作及其目的:
读取图片
cv2.imread() 函数加载图像。转换色彩空间
cv2.cvtColor() 进行色彩空间转换。滤波
cv2.GaussianBlur)、均值滤波 (cv2.blur) 和双边滤波 (cv2.bilateralFilter) 等。绘制图形
cv2.line()、cv2.rectangle()、cv2.circle() 和 cv2.polylines() 来绘制直线、矩形、圆形或多边形。边缘检测
cv2.Canny) 或 Sobel 操作符 (cv2.Sobel)。阈值操作
cv2.threshold() 用于二值化图像。Sobel 滤波
cv2.Sobel() 计算图像梯度。文件保存
cv2.imwrite() 将图像保存到磁盘。
目的:保存处理后的图像以便将来使用或分享。
此外,还有其他重要的OpenCV功能,如:
cv2.equalizeHist) 提升图像对比度。cv2.matchTemplate) 用于查找一个图像中的另一个小图像的位置。这些基础操作和高级特性共同构成了强大的工具集,可以用来开发从简单的图像编辑应用到复杂的计算机视觉系统。 这些操作是构建复杂图像处理流水线的基础,可以单独使用,也可以组合起来解决更复杂的视觉问题。例如,预处理阶段可能会包括去噪、边缘检测和形态学操作;而在后处理阶段,则可能会涉及阈值操作和绘制几何图形来标注或解释结果。以上这些算子仅仅是OpenCV库的一小部分的内容,但是它们是支持我们进行复杂操作的基础。
在学习OpenCV的初期,可能会觉得每个算子或函数就像是独立的知识点,虽然能够理解它们各自的功能和用法,但当面对实际问题时,却难以将这些知识点有效地组合起来解决问题。这是因为从理论到实践的应用需要一个过渡的过程,在这个过程中,不仅需要掌握单个算子的操作,还需要学会如何根据具体的需求选择合适的算子,并且合理地调整参数以达到预期的效果。
OpenCV的强大之处在于它提供了丰富的图像处理功能,但这也意味着使用它的难点在于:
本文章主要讲述如何在边缘端设备上使用OpenCV。本次使用的边缘端设备是凌智电子开发的凌智视觉模块,具体如下:
如对该边缘端设备感兴趣,可到Gitee仓库:凌智视觉模块查看该设备的具体信息。
接下来我们通过几个例子来介绍如何在边缘端设备使用OpenCV进行形状检测。
import lockzhiner_vision_module.cv2 as cv2
from lockzhiner_vision_module.edit import Edit
import time
import sys
if __name__ == "__main__":
args = sys.argv
if len(args) != 3:
print("Need model path. Example: python test_capture.py width height")
exit(1)
edit = Edit()
edit.start_and_accept_connection()
video_capture = cv2.VideoCapture()
video_capture.set_width(int(args[1]))
video_capture.set_height(int(args[2]))
if video_capture.open(0) is False:
print("Failed to open capture")
exit(1)
while True:
read_index = 0
total_time_ms = 0
for i in range(30):
start_time = time.time()
ret, mat = video_capture.read()
if ret is False:
continue
end_time = time.time()
# 转换为灰度图像
gray = cv2.cvtColor(mat, cv2.COLOR_BGR2GRAY)
# 高斯模糊
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 二值化
_, binary = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY_INV)
edges = cv2.Canny(binary, 30, 200)
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
# 近似轮廓
# 计算轮廓周长
epsilon = 0.02 * cv2.arcLength(contour, True)
# 将轮廓近似为多边形
if epsilon < 15:
continue
approx = cv2.approxPolyDP(contour, epsilon, True)
# 如果近似轮廓有4个顶点,则认为是矩形
if len(approx) == 4:
cv2.putText(mat, "Rectangle", (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
cv2.drawContours(mat, [approx], -1, (0, 255, 0), 2)
edit.print(mat)
total_time_ms += end_time - start_time
read_index += 1
print(f"FPS is {1.0 / (total_time_ms / read_index)}")
在这一段代码中的检测效果如下图所示
但是当我们只想要外部的矩形时,我们可以怎么做呢?
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

效果如上图所示,接下来我们就得深究一下cv2.findContours mode 参数 和 method 参数的区别及作用了,我就不一一演示了,大家伙可以自行实验,毕竟我也踩过。
mode: 轮廓检索模式,定义了如何检索轮廓及其层次结构。有以下几种选择:
cv2.RETR_EXTERNAL: 只检索最外层的轮廓。cv2.RETR_LIST: 检索所有的轮廓,但不建立它们之间的等级关系。cv2.RETR_CCOMP: 检索所有的轮廓,并将它们组织为两级层次结构:顶层是外部边界,次级是孔洞。cv2.RETR_TREE: 检索所有轮廓,并重建完整的包含关系。method: 轮廓近似方法,决定了轮廓的精度。有以下几种选择:
cv2.CHAIN_APPROX_NONE: 存储所有的轮廓点,即没有近似。cv2.CHAIN_APPROX_SIMPLE: 压缩水平、垂直和对角方向上的元素,只保留端点。cv2.CHAIN_APPROX_TC89_L1: 使用一种称为 Teh-Chin 链逼近算法的更复杂的压缩方式。cv2.CHAIN_APPROX_TC89_KCOS: 同样使用 Teh-Chin 链逼近算法,但与 L1 不同,它是基于 KCOS 的。OpenCV 提供了 HoughCircles 函数来检测圆形。Hough变换是一种用于从图像中提取几何形状(如直线、圆等)的技术,它通过参数空间的投票机制来实现。对于圆形检测,Hough变换可以识别出满足特定条件的圆形结构。下面是使用 OpenCV 进行圆形检测的基本步骤:
首先加载需要检测圆的图像,并将其转换为灰度图,因为颜色信息对于圆形检测不是必要的。
调用 cv2.HoughCircles 函数进行圆形检测。该函数接受几个重要参数:
method:定义了检测方法,通常使用 cv2.HOUGH_GRADIENT。dp:累加器分辨率与图像分辨率的反比。dp=1 表示累加器具有与输入图像相同的分辨率。minDist:检测到的圆心之间的最小距离。如果设置得太小,可能会检测到多个相邻的圆;如果太大,可能会漏检一些圆。param1:Canny边缘检测的高阈值,低阈值是高阈值的一半。param2:累加器阈值。该阈值越小,检测到的圆越多(包括不完美的圆)。越大则只检测到更明显的圆。minRadius 和 maxRadius:分别为检测到的圆的最小和最大半径。请注意,上述参数 (dp, minDist, param1, param2, minRadius, maxRadius) 需要根据具体应用场景调整,以获得最佳检测效果。例如,不同的光照条件、背景复杂度或者目标圆的大小都会影响这些参数的选择。
实例代码
from lockzhiner_vision_module.cv2 import VideoCapture
import lockzhiner_vision_module.cv2 as cv2
from lockzhiner_vision_module.edit import Edit
import time
import sys
pi = 3.14159265358979323846
if __name__ == "__main__":
args = sys.argv
if len(args) != 3:
print("Need model path. Example: python test_capture.py width height")
exit(1)
edit = Edit()
edit.start_and_accept_connection()
video_capture = VideoCapture()
video_capture.set_width(int(args[1]))
video_capture.set_height(int(args[2]))
if video_capture.open(0) is False:
print("Failed to open capture")
exit(1)
while True:
read_index = 0
total_time_ms = 0
for i in range(30):
start_time = time.time()
ret, mat = video_capture.read()
if ret is False:
continue
end_time = time.time()
# 转换为灰度图像
# 转换为灰度图像
gray = cv2.cvtColor(mat, cv2.COLOR_BGR2GRAY)
# 使用高斯模糊减少噪声
blurred = cv2.GaussianBlur(gray, (9, 9), 2)
# 使用 HoughCircles 检测圆形
circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, dp=1, minDist=50,
param1=50, param2=30, minRadius=120, maxRadius=250)
# print(circles)
if circles is not None:
# 在图像上绘制检测到的圆
for i in circles[0]:
center = (int(i[0]), int(i[1]))
radius = int(i[2])
cv2.putText(mat, "circle", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
# 绘制圆心
cv2.circle(mat, center, 1, (0, 100, 100), 3)
# 绘制圆
cv2.circle(mat, center, radius, (0, 255, 0), 3)
edit.print(mat)
total_time_ms += end_time - start_time
read_index += 1
print(f"FPS is {1.0 / (total_time_ms/read_index)}")
检测效果图 :
更多回帖