随笔 - 149,  文章 - 0,  评论 - 0,  阅读 - 12257

OpenCV 中提供了 150 多种颜色空间转换方法。但我们将只研究两个,它们是使用最广泛的:BGR \leftrightarrow Gray 和 BGR \leftrightarrow HSV。<br>

对于颜色转换,我们使用函数 cv.cvtColor(input_image, flag),其中 flag 确定转换的类型。

对于 BGR \rightarrow 灰色转换,我们使用标志 cv.COLOR_BGR2GRAY。同样,对于 BGR \rightarrow HSV,我们使用标志 cv.COLOR_BGR2HSV。要获取其他标志,只需在 Python 终端中运行以下命令:&amp;amp;lt;span&amp;amp;gt;&amp;amp;lt;span&amp;amp;gt;&amp;amp;lt;span id="MathJax-Span-14" class="mrow"&amp;amp;gt;&amp;amp;lt;span id="MathJax-Span-15" class="mo"&amp;amp;gt;&amp;rarr;&amp;amp;lt;span&amp;amp;gt;&amp;amp;lt;span&amp;amp;gt;&amp;amp;lt;span id="MathJax-Span-17" class="mrow"&amp;amp;gt;&amp;amp;lt;span id="MathJax-Span-18" class="mo"&amp;amp;gt;&amp;rarr;

>>> 将 CV2 导入为 CV
>>>标志 = [i for i in dir(CV) if i.startswith('COLOR_')]
>>> print( 标志 )

 

注意对于HSV,色调范围为[0,179],饱和度范围为[0,255],值范围为[0,255]。不同的软件使用不同的规模。因此,如果要将 OpenCV 值与它们进行比较,则需要对这些范围进行归一化。

对象跟踪

现在我们知道了如何将 BGR 图像转换为 HSV,我们可以使用它来提取有色对象。在 HSV 中,表示颜色比在 BGR 颜色空间中更容易。在我们的应用程序中,我们将尝试提取一个蓝色的物体。所以这里是方法:

  • 拍摄视频的每一帧
  • 从 BGR 转换为 HSV 颜色空间
  • 我们将 HSV 图像的阈值设置为一系列蓝色
  • 现在单独提取蓝色物体,我们可以在该图像上做任何我们想做的事
复制代码
 1 import cv2 as cv
 2 import numpy as np
 3 
 4 # 初始化摄像头
 5 cap = cv.VideoCapture(0)
 6 
 7 while True:
 8     # 读取一帧
 9     ret, frame = cap.read()
10     if not ret:
11         break  # 如果无法读取帧,则退出循环
12 
13     # 将BGR图像转换为HSV
14     hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
15 
16     # 定义HSV中蓝色的范围
17     lower_blue = np.array([110, 50, 50])
18     upper_blue = np.array([130, 255, 255])
19 
20     # 根据蓝色范围创建掩码
21     mask = cv.inRange(hsv, lower_blue, upper_blue)
22 
23     # 使用掩码和原始帧进行按位与操作,获取蓝色部分
24     res = cv.bitwise_and(frame, frame, mask=mask)
25 
26     # 显示结果
27     cv.imshow('Frame', frame)
28     cv.imshow('Mask', mask)
29     cv.imshow('Result', res)
30 
31     # 按'q'键退出
32     if cv.waitKey(5) & 0xFF == ord('q'):
33         break
34 
35     # 释放摄像头资源并关闭所有窗口
36 cap.release()
37 cv.destroyAllWindows()
复制代码

 

二、图像的几何变换

  • 学习对图像应用不同的几何变换,如平移、旋转、仿射变换等。
  • 使用以下函数:cv.getPerspectiveTransform

2.1转换

OpenCV 提供了两个转换函数,cv.warpAffine 和 cv.warpPerspective,我们可以使用它们执行各种转换。cv.warpAffine 采用 2x3 转换矩阵,而 cv.warpPerspective 采用 3x3 转换矩阵作为输入。

缩放

缩放只是调整图像的大小。OpenCV 带有一个函数 cv.resize() 用于此。可以手动指定图像的大小,也可以指定缩放因子。使用了不同的插值方法。更优选的插值方法是cv.INTER_AREA用于缩小和cv.INTER_CUBIC(慢速)&cv.INTER_LINEAR用于缩放。默认情况下,插值方法 cv.INTER_LINEAR 用于所有调整大小目的。我们可以使用以下任一方法调整输入图像的大小:

复制代码
 1 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\5.jpg')
 2 assert img is not None, "无法读取文件,请使用 os.path.exists() 检查文件是否存在"
 3 # 缩放图片,fx和fy分别表示水平和垂直方向的缩放比例,这里都设置为2,表示将图片放大两倍
 4 # 注意:Python中函数调用时,参数之间使用逗号分隔,且不要在参数名之间加空格
 5 res_fx_fy = cv.resize(img, None, fx=2, fy=2, interpolation=cv.INTER_CUBIC)
 6 
 7 cv.imshow('Original Image', img)
 8 cv.imshow('Resized with fx and fy', res_fx_fy)
 9 cv.waitKey(0)  # 等待按键
10 cv.destroyAllWindows()  # 关闭所有窗口
11 
12 # 保存图像(可选)
13 cv.imwrite('resized_fx_fy.jpg', res_fx_fy)
复制代码

哈哈哈,,,,,,,,,,,,,,一屏截不下

 

三、平移

复制代码
 1 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\5.jpg', cv.IMREAD_GRAYSCALE)
 2 assert img is not None, "无法读取文件,请使用 os.path.exists() 检查文件是否存在"
 3 # 获取图像的行数和列数
 4 width, height= img.shape
 5 # 定义平移矩阵
 6 M = np.float32([[1, 0, 100], [0, 1, 50]])
 7 dst = cv.warpAffine(img, M, (width, height))  # 没有先后顺序
 8 cv.imshow('img', dst)
 9 cv.waitKey(0)
10 cv.destroyAllWindows()
复制代码

 cv.warpAffine 函数的第三个参数是输出图像的大小,其形式应为(宽度、高度)。记住宽度=列数,高度=行数

四、旋转

OpenCV 提供了一个函数 cv.getRotationMatrix2D。看看下面的例子,它将图像相对于中心旋转 90 度,而不进行任何缩放。

复制代码
 1 # 旋转
 2 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png', cv.IMREAD_GRAYSCALE)
 3 assert img is not None, "无法读取文件,请使用 os.path.exists() 检查文件是否存在"
 4 # 获取图像的尺寸
 5 height, width = img.shape  # 注意:高度在前,宽度在后
 6 
 7 # 旋转中心为图像中心
 8 center = (width // 2, height // 2)
 9 
10 # 生成旋转矩阵,旋转90度,缩放因子为1
11 M = cv.getRotationMatrix2D(center, 90, 1)
12 
13 # 计算旋转后图像的新尺寸
14 # 注意:当旋转90度或270度时,宽度和高度会互换
15 new_width, new_height = height, width
16 
17 # 应用旋转
18 dst = cv.warpAffine(img, M, (new_width, new_height))
19 
20 # 显示结果图像
21 cv.imshow('Rotated Image', dst)
22 cv.waitKey(0)  # 等待按键
23 cv.destroyAllWindows()  # 关闭所有窗口
复制代码

 

五、形态学转变

形态变换是基于图像形状的一些简单操作。它通常在二进制图像上执行。它需要两个输入,一个是我们的原始图像,第二个被称为结构元素内核,它决定了操作的性质。两个基本的形态算子是侵蚀和扩张。然后它的变体形式,如打开、关闭、梯度等也开始发挥作用。我们将在下图的帮助下一一看到它们:

      原图

 

5.1. 侵蚀

侵蚀的基本概念就像土壤侵蚀一样,它侵蚀了前景物体的边界(始终尝试保持前景为白色)。那么它有什么作用呢?内核在图像中滑动(如在 2D 卷积中)。只有当内核下的所有像素都为 1 时,原始图像中的像素(1 或 0)才会被视为 1,否则它将被侵蚀(变为零)。

因此,发生的情况是,所有靠近边界的像素都将被丢弃,具体取决于内核的大小。因此,图像中前景物体的厚度或大小减小,或者只是白色区域减小。它对于去除小的白噪声(正如我们在colorspace章节中看到的那样),分离两个连接的对象等很有用。

复制代码
 1 # 侵蚀
 2 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png', cv.IMREAD_GRAYSCALE)
 3 assert img is not None, "无法读取文件,请使用 os.path.exists() 检查文件是否存在"
 4 # 定义一个5x5的内核
 5 kernel = np.ones((5, 5), np.uint8)
 6 # 对图像进行侵蚀操作
 7 img_erosion = cv.erode(img, kernel, iterations=1)
 8 
 9 cv.imshow('Rotated Image', img_erosion)  
10 cv.waitKey(0)  # 等待按键
11 cv.destroyAllWindows()  # 关闭所有窗口
复制代码

 

5.2. 扩张

1 膨胀 = cv.dilate(img,kernel,iterations = 1)

 

变换

OpenCV 提供了两个转换函数,**cv.warpAffine** 和 cv.warpPerspective**,可以进行各种转换。 **cv.warpAffine 采用 2x3 变换矩阵,而 cv.warpPerspective 采用 3x3 变换矩阵作为输入。

缩放

缩放是调整图片的大小。 OpenCV 使用 cv.resize() 函数进行调整。可以手动指定图像的大小,也可以指定比例因子。可以使用不同的插值方法。对于下采样(图像上缩小),最合适的插值方法是 cv.INTER_AREA 对于上采样(放大),最好的方法是 cv.INTER_CUBIC (速度较慢)和 cv.INTER_LINEAR (速度较快)。默认情况下,所使用的插值方法都是 cv.INTER_AREA 。你可以使用如下方法调整输入图片大小:

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC)
#OR
height, width = img.shape[:2]
res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)

平移变换

平移变换是物体位置的移动。如果知道 (x,y) 方向的偏移量,假设为 (t_x,t_y)**,则可以创建如下转换矩阵 **M:

图片

您可以将变换矩阵存为 np.float32 类型的 numpy 数组,并将其作为 cv.warpAffine 的第二个参数。请参见以下转换(100,50)的示例:

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv.warpAffine(img,M,(cols,rows))
cv.imshow('img',dst)
cv.waitKey(0)
cv.destroyAllWindows()

警告

cv.warpAffine 函数的第三个参数是输出图像的大小,其形式应为(宽度、高度)。记住宽度=列数,高度=行数。

结果:

图片

旋转

以 图片角度旋转图片的转换矩阵形式为:

图片

但 Opencv 提供了可变旋转中心的比例变换,所以你可以在任意位置旋转图片,修改后的转换矩阵为:

图片

其中:

图片

为了找到这个转换矩阵,opencv 提供了一个函数, cv.getRotationMatrix2D 。请查看下面的示例,它将图像相对于中心旋转 90 度,而不进行任何缩放。

img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
# cols-1 and rows-1 are the coordinate limits.
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv.warpAffine(img,M,(cols,rows))

结果:

图片

仿射变换

在仿射变换中,原始图像中的所有平行线在输出图像中仍然是平行的。为了找到变换矩阵,我们需要从输入图像中取三个点及其在输出图像中的对应位置。然后 cv.getAffineTransform 将创建一个 2x3 矩阵,该矩阵将传递给 cv.warpAffine 

复制代码
 1 import numpy as np
 2 import cv2 as cv
 3 from matplotlib import pyplot as plt
 4 
 5 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png')
 6 
 7 rows, cols, ch = img.shape
 8 pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
 9 pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
10 M = cv.getAffineTransform(pts1, pts2)
11 dst = cv.warpAffine(img, M, (cols, rows))
12 plt.subplot(121), plt.imshow(img), plt.title('Input')
13 plt.subplot(122), plt.imshow(dst), plt.title('Output')
14 plt.show()
复制代码

 

透视变换

对透视转换,你需要一个 3x3 变换矩阵。即使在转换之后,直线也将保持直线。要找到这个变换矩阵,需要输入图像上的 4 个点和输出图像上的相应点。在这四点中,任意三点不应该共线。然后通过 cv.getPerspectiveTransform 找到变换矩阵。然后对这个 3x3 变换矩阵使用 **cv.warpPerspective**

复制代码
 1 import numpy as np
 2 import cv2 as cv
 3 from matplotlib import pyplot as plt
 4 
 5 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png')
 6 
 7 rows, cols, ch = img.shape
 8 pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
 9 pts2 = np.float32([[0, 0], [200, 0], [0, 200], [200, 200]])
10 M = cv.getPerspectiveTransform(pts1, pts2)
11 dst = cv.warpPerspective(img, M, (200, 200))
12 plt.subplot(121), plt.imshow(img), plt.title('Input')
13 plt.subplot(122), plt.imshow(dst), plt.title('Output')
14 plt.show()
复制代码

 

 

 

 

六、图像阈值

函数:cv.thresholdcv.adaptiveThreshold

如果像素值大于阈值,则会被赋为一个值(可能为白色),否则会赋为另一个值(可能为黑色)。使用的函数是 cv.threshold。第一个参数是源图像,它应该是灰度图像。第二个参数是阈值,用于对像素值进行分类。第三个参数是 maxval,它表示像素值大于(有时小于)阈值时要给定的值。opencv 提供了不同类型的阈值,由函数的第四个参数决定。不同的类型有:

复制代码
 1 import cv2 as cv
 2 from cffi.backend_ctypes import xrange
 3 from matplotlib import pyplot as plt
 4 
 5 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png', 0)
 6 ret, thresh1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
 7 ret, thresh2 = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
 8 ret, thresh3 = cv.threshold(img, 127, 255, cv.THRESH_TRUNC)
 9 ret, thresh4 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO)
10 ret, thresh5 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO_INV)
11 titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
12 images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
13 for i in xrange(6):
14     plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
15     plt.title(titles[i])
16     plt.xticks([]), plt.yticks([])
17 plt.show()
复制代码

 

自适应阈值

我们采用自适应阈值。在此,算法计算图像的一个小区域的阈值。因此,我们得到了同一图像不同区域的不同阈值,对于不同光照下的图像,得到了更好的结果

 它有三个“特殊”输入参数,只有一个输出参数

Adaptive Method-它决定如何计算阈值。

Block Size-它决定了计算阈值的窗口区域的大小。

C-它只是一个常数,会从平均值或加权平均值中减去该值。

复制代码
 1 import cv2 as cv
 2 from cffi.backend_ctypes import xrange
 3 from matplotlib import pyplot as plt
 4 
 5 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png', 0)
 6 img = cv.medianBlur(img, 5)
 7 ret, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
 8 th2 = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_MEAN_C, \
 9                            cv.THRESH_BINARY, 11, 2)
10 th3 = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, \
11                            cv.THRESH_BINARY, 11, 2)
12 titles = ['Original Image', 'Global Thresholding (v = 127)',
13           'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
14 images = [img, th1, th2, th3]
15 for i in xrange(4):
16     plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
17     plt.title(titles[i])
18     plt.xticks([]), plt.yticks([])
19 plt.show()
复制代码

 

Otsu 二值化

在全局阈值化中,我们使用一个任意的阈值,对吗?那么,我们如何知道我们选择的值是好的还是不好的呢?答案是,试错法。但是考虑一个双峰图像(简单来说,双峰图像是一个直方图有两个峰值的图像)。对于那个图像,我们可以近似地取这些峰值中间的一个值作为阈值,对吗?这就是 Otsu 二值化所做的。所以简单来说,它会自动从双峰图像的图像直方图中计算出阈值。(对于非双峰图像,二值化将不准确。)

为此,我们使用了 cv.threshold 函数,但传递了一个额外的符号 cv.THRESH_OTSU 。对于阈值,只需传入零。然后,该算法找到最佳阈值,并作为第二个输出返回 retval。如果不使用 otsu 阈值,则 retval 与你使用的阈值相同。

复制代码
 1 import cv2 as cv
 2 from cffi.backend_ctypes import xrange
 3 from matplotlib import pyplot as plt
 4 
 5 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png', 0)
 6 # 全局阈值
 7 ret1, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
 8 # Otsu 阈值
 9 ret2, th2 = cv.threshold(img, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
10 # 经过高斯滤波的 Otsu 阈值
11 blur = cv.GaussianBlur(img, (5, 5), 0)
12 ret3, th3 = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
13 # 画出所有的图像和他们的直方图
14 images = [img, 0, th1,
15           img, 0, th2,
16           blur, 0, th3]
17 titles = ['Original Noisy Image', 'Histogram', 'Global Thresholding (v=127)',
18           'Original Noisy Image', 'Histogram', "Otsu's Thresholding",
19           'Gaussian filtered Image', 'Histogram', "Otsu's Thresholding"]
20 for i in xrange(3):
21     plt.subplot(3, 3, i * 3 + 1), plt.imshow(images[i * 3], 'gray')
22     plt.title(titles[i * 3]), plt.xticks([]), plt.yticks([])
23     plt.subplot(3, 3, i * 3 + 2), plt.hist(images[i * 3].ravel(), 256)
24     plt.title(titles[i * 3 + 1]), plt.xticks([]), plt.yticks([])
25     plt.subplot(3, 3, i * 3 + 3), plt.imshow(images[i * 3 + 2], 'gray')
26     plt.title(titles[i * 3 + 2]), plt.xticks([]), plt.yticks([])
27 plt.show()
复制代码

 

 

七、OpenCV中的轮廓

函数:cv.findContours() ,cv.drawContours()

  • 什么是轮廓?

    轮廓可以简单地解释为连接具有相同颜色或强度的所有连续点(沿边界)的曲线。轮廓是用于形状分析以及对象检测和识别的有用工具。
  • 为了获得更高的准确性,请使用二进制图像。因此,在找到轮廓之前,请应用阈值或 Canny 边缘检测。
  • 从OpenCV 3.2开始,**findContours()** 不再修改源图像。
  • 在OpenCV中,找到轮廓就像从黑色背景中找到白色物体。因此请记住,要找到的对象应该是白色,背景应该是黑色。
复制代码
 1 import cv2 as cv
 2 
 3 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png')
 4 
 5 imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
 6 ret, thresh = cv.threshold(imgray, 127, 255, 0)
 7 contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
 8 cv.drawContours(img, contours, -1, (0, 255, 0), 3)
 9 cv.imshow('image', img)
10 cv.waitKey(0)
11 cv.destroyAllWindows()
复制代码

 

在 cv.findContours() 函数中有三个参数,第一个是源图像,第二个是轮廓检索模式,第三个是轮廓逼近方法。并输出轮廓和层次。轮廓是图像中所有轮廓的Python列表。每个单独的轮廓都是对象边界点的(x,y)坐标的Numpy数组。

 

八、模板匹配

模板匹配是一种在较大图像中搜索和查找模板图像位置的方法。为此,OpenCV 带有一个函数 cv.matchTemplate() 。它只是在输入图像上滑动模板图像(如在 2D 卷积中),并比较模板图像下的模板和输入图像的补丁

如果输入图像的大小(WxH)且模板图像的大小(wxh),则输出图像的大小为(W-w + 1,H-h + 1)。得到结果后,可以使用 cv.minMaxLoc() 函数查找最大/最小值的位置。将其作为矩形的左上角,取(w,h)作为矩形的宽度和高度。那个矩形是你的模板区域。

如果使用cv.TM_SQDIFF函数作为比较的方法, 最小值作为匹配值。

 

OpenCV 中的模板匹配

复制代码
 1 import cv2 as cv
 2 from matplotlib import pyplot as plt
 3 
 4 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png', 0)
 5 img2 = img.copy()
 6 template = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\6.jpg', 0)
 7 w, h = template.shape[::-1]
 8 # All the 6 methods for comparison in a list
 9 methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
10            'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']
11 for meth in methods:
12     img = img2.copy()
13     method = eval(meth)
14     # Apply template Matching
15     res = cv.matchTemplate(img, template, method)
16     min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
17     # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
18     if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
19         top_left = min_loc
20     else:
21         top_left = max_loc
22     bottom_right = (top_left[0] + w, top_left[1] + h)
23     cv.rectangle(img, top_left, bottom_right, 255, 2)
24     plt.subplot(121), plt.imshow(res, cmap='gray')
25     plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
26     plt.subplot(122), plt.imshow(img, cmap='gray')
27     plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
28     plt.suptitle(meth)
29     plt.show()
复制代码

(其中一个比较截图)

 

模板与多个对象匹配

假设您正在搜索的对象在图中出现了多次, cv.minMaxLoc() 将不会为你提供所有的匹配点。在这种情况下,我们将使用阈值。所以在这个例子中,我们将使用着名游戏 Mario 的截图,并在其中找到硬币

复制代码
 1 import cv2 as cv
 2 import numpy as np
 3 from matplotlib import pyplot as plt
 4 img_rgb = cv.imread('mario.png')
 5 img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
 6 template = cv.imread('mario_coin.png',0)
 7 w, h = template.shape[::-1]
 8 res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)
 9 threshold = 0.8
10 loc = np.where( res >= threshold)
11 for pt in zip(*loc[::-1]):
12     cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
13 cv.imwrite('res.png',img_rgb)
复制代码

 

 

 

九、霍夫圆变化

使用霍夫变换来查找图像中的圆圈

函数: cv.HoughCircles()

圆圈在数学上表示为(xxcenter)2+(yycenter)2=r2其中(xcenter,ycenter)是圆的中心,r 是圆的半径。从这个公式来看,得知我们有三个参数,这样我们就需要一个三维度的累加器来做霍夫变换了,这样效率是非常低的。所以 OpenCV 用了更巧妙的方法Hough Gradient Method ,它利用了边缘的梯度信息。 我们在这里使用的函数是 cv.HoughCircles() 

复制代码
 1 import numpy as np
 2 import cv2 as cv
 3 
 4 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png', 0)
 5 img = cv.medianBlur(img, 5)
 6 cimg = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
 7 circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 20,
 8                           param1=50, param2=30, minRadius=0, maxRadius=0)
 9 circles = np.uint16(np.around(circles))
10 for i in circles[0, :]:
11     # draw the outer circle
12     cv.circle(cimg, (i[0], i[1]), i[2], (0, 255, 0), 2)
13     # draw the center of the circle
14     cv.circle(cimg, (i[0], i[1]), 2, (0, 0, 255), 3)
15 cv.imshow('detected circles', cimg)
16 cv.waitKey(0)
17 cv.destroyAllWindows()
复制代码

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
posted on   认真的六六  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示