在近期对计算机视觉的学习中,有一些心得与感受和大家一起分享,并且也说一些我做题目用到的函数和一些常见错误
TEST1:图像边框
对矩形的轮廓识别与绘制,难点在于利用色彩来选中红色图形与绿色图形进行处理(后面的几个题也是利用了相同的方法对图像进行特定操作)
我们在对图像进行处理时,总会有一个读取图像-操作图像-显示图像-(保存图像)的流程
基础不变的就是图像读取
import cv2
image = cv2.imread('picture.png')# 读取图像
对于特殊操作,还可以引入一些特殊库
import numpy as np
难点:转换到HSV颜色空间进行操作(注意读取后的图像是非黑即白的二度值,便于操作)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)#转换图像为hsv
# 定义红色的HSV范围
lower_red = np.array([0, 120, 70])
upper_red = np.array([10, 255, 255])
mask1 = cv2.inRange(hsv, lower_red, upper_red)
边缘检测主要是对灰度值进行操作和分析的,所以要将提取的二度值图像转为灰度图
彩色图像灰度处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.cvtColor(end, cv2.COLOR_BGR2GRAY)
在使用边缘检测,绘制边缘
# 应用Canny边缘检测
edges = cv2.Canny(gray, 100, 200)
## 查找轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(image, contours, -1, (0, 0, 0), 3)
最后是最固定的在指定窗口内显示图像(同时包含窗口创建与显示)
# 显示结果
cv2.imshow('Result1', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
最后两行是为了使图像显示持续。
TEST2:图像特殊处理+边框
WAY1:霍夫圆处理
对非连续图像进行外部轮廓,难点在于对残缺图像的处理,其处于最小图形框内
img_gray = cv2.imread('picture.png', 0)
img_color = cv2.imread('picture.png', -1) # 原始图像,包含alpha通道,保留图像透明度?
对图像降噪以及霍夫圆函数
# 应用中值滤波
img_blurred = cv2.medianBlur(img_gray, 5)
# 使用霍夫圆变换检测圆
circles = cv2.HoughCircles(img_blurred, cv2.HOUGH_GRADIENT, 2, 100,#dp累加器分辨率与图像分辨率的反比
param1=50, param2=30, minRadius=85, maxRadius=200)#圆的精度,以及半径选取
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
cv2.circle(img_color, (i[0], i[1]), i[2], (0, 0, 0), 2)#园周边轮廓
cv2.circle(img_color, (i[0], i[1]), 2, (0, 0, 255), 12) # 中心点的颜色改为红色以便区分
图像显示(即以一个图形的顶点为圆心画圆)
WAY2开运算闭运算
先使用HSV对指定颜色图形进行区分,使其转化二度值图像
闭运算
kernel = np.ones((3,3 ), np.uint8)#建立核(计算像素基值)
r1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, kernel,iterations=3)
#闭运算,使间隙融合
r1 = cv2.morphologyEx(r1, cv2.MORPH_OPEN, kernel,iterations=1)
#开运算,使合并扩散图像更为规范
可以看出,使用开闭运算得到的图形更为规范,效果也更符合要求。
TEST3角点寻找
这考验的是对函数的运用和HSV颜色区
重点:识别角和绘制角点
# 识别角
corners = cv2.goodFeaturesToTrack(mask2, maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)
# 绘制角点(如果 corners 不为空)
if corners is not None:
corners = np.int0(corners).reshape((-1, 2)) # 如果需要转换,并且 corners 不是整数,则进行转换并调整形状
for i in corners:
x, y = i.ravel()
cv2.circle(img, (x, y), 6, (0, 0,0), -1) # 使用黑色绘制角点
效果展示
TEST4:面积计算并显示
对处理区域进行识别
# 转换为 HSV 色彩空间
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 设置绿色 HSV 阈值
lower_green = np.array([50, 100, 50])
upper_green = np.array([70, 255, 255])
# 创建掩码
mask_green = cv2.inRange(hsv, lower_green, upper_green)#颜色过滤,区域定位
查找轮廓,针对二度值图像
# 查找轮廓
contours, hierarchy = cv2.findContours(mask_green, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
重难点:计算面积函数(第一个轮廓是因为只有一个轮廓)
# 假设我们想要处理第一个轮廓
area = cv2.contourArea(contours[0])
print(f"第一个轮廓的面积是: {area}")
那么,我们该如何在计算机里用文字体现所需内容呢?绘制文本就是一大学习要点
# 检查是否找到轮廓
if contours:
# 假设我们想要处理第一个轮廓
area = cv2.contourArea(contours[0])
print(f"第一个轮廓的面积是: {area}")
# 设置文本参数
text = f"Area: {area}"
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1
font_color = (0, 0, 0) # 黑色
line_type = 2
max_contour = max(contours, key=cv2.contourArea)#针对绿色图像
# 计算轮廓的矩
M = cv2.moments(max_contour)
# 计算中心点
if M["m00"] != 0:
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
else:
cX, cY = 0, 0
# 在原始图像上绘制面积文本
cv2.putText(img, text, (cX,cY), font, font_scale, font_color, line_type)
请注意,为了满足题目在图形中心显示文本的要求,我们不得不去计算图像的中心点x,y:并文本放置于计算出的(x,y)内
可以看见,Area的A与三角形的顶点在一条直线上,就完成了所需条件。
TEST5多个图像的最小矩形框计算
这是我找函数最难的一题/-\,理解其实很简单,但是计算机思维里面我还没有接触到识别图像直接计算共同外界矩形的函数,后面经过查找发现了一个好玩的——OBB包围盒
先计算出每个图像的最小包围矩形
然后在通过对顶点的值域计算,求出共同的最小包围矩形
图像是我想要的那么一回事了,但是代码的推演运算还是很陌生的,就纠结在如何使红色矩形脱离最小矩形的运算中,简单的HSV筛选似乎不能直接套用。
后面调试,发现其实也是对一个二度值的个图像:最小矩形框计算——矩形框顶点计算——顶点整型化后取最小包围矩形
import numpy as np
import cv2
src = cv2.imread('picture.png')
cv2.imshow('src', src)
split_res = src.copy() # 显示每个轮廓结构
merge_res = src.copy() # 显示合并后轮廓结构,复制图像便于操作和体现
# # 将图像从BGR转换到HSV
hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
# 定义颜色范围
lower_blue = np.array([100, 120, 70])
upper_blue = np.array([140, 255, 255])
lower_green = np.array([60, 100, 50])
upper_green = np.array([180, 255, 255])
# 创建掩模
mask1 = cv2.inRange(hsv, lower_blue, upper_blue)
mask2 = cv2.inRange(hsv, lower_green, upper_green)
mask = cv2.bitwise_or(mask1, mask2)
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
merge_list = []#另一个空间
for cnt in contours:
rect = cv2.minAreaRect(cnt)#计算最小面积矩形
box = cv2.boxPoints(rect)#获取矩形顶点
box = np.int0(box)#浮点变整点
split_res = cv2.drawContours(split_res, [box], 0, (0, 0, 255), 2)#分别绘制矩形
merge_list.append(cnt)#在list上存储当前轮廓
contours_merge = np.vstack([merge_list[0], merge_list[1]])
for i in range(2, len(merge_list)):#循环合并剩余轮廓
contours_merge = np.vstack([contours_merge, merge_list[i]])
rect2 = cv2.minAreaRect(contours_merge)#计算合并后轮廓的最小面积矩形
box2 = cv2.boxPoints(rect2)#获取最小面积矩形的顶点
box2 = np.int0(box2)
merge_res = cv2.drawContours(merge_res, [box2], 0, (0, 0, 0), 2)#绘制矩形
cv2.imshow('merge_res', merge_res)
cv2.waitKey(0)
cv2.destroyAllWindows()
当当当当当!要求的效果就体现出来啦!
不过图像的倾斜角还没有体现出来emmm,看大佬演示的时候说只需要一个小函数,不过我没有找到那个小函数是什么哈哈哈哈哈,然后在网上找到的函数又太复杂,好几大行?
angle = rect[2]
# Output the result and angle
plt.imshow(cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB))
plt.title(f"Angle: {angle:.2f} degrees")
但是在我的代码里面它跑不起来啊啊啊啊,无奈。小小遗憾,不过今天晚上应该能解决掉,
加油加油!
总结
感悟
虽然困难重重,不过看着对题目从恐惧变成了解再到熟悉相应的知识点和函数,真的是很有成就感,而且从零到一的过程也很值得赞叹!成长耶耶耶!
不过距离正真的指标还需要自己走很多路,把C语言完结,还有单片机没开始,其他计算机视觉的知识点也不熟练……有方向总是好的
易错及经验
1.图片和代码放在同一个文件
2.注意对象名的统一性
3.区分函数对二度值和灰度值的要求
4.特殊的函数应用要调取想要的库
5.不要拼写错误,不要编写错误!!!
6.可以利用cv2.imshow()来检验步骤的失误
7.不要羞于询问,学长学姐,同学甚至文心一言,都是你很好的助手,求助也是一种能力!
8.有做事的决心和信心,就能坚持做好事情。
标签:总结,入门,merge,cv2,OPENCV,contours,图像,np,轮廓 From: https://blog.csdn.net/liliumH/article/details/142391216