7. 在 Python OpenCV 寻找目标区域以及边缘扩展的解决方案
本系列专栏写作方式
本系列专栏首发在 易百纳技术社区 ,写作将采用首创的问答式写作形式,快速让你学习到 OpenCV 的初级、中级、高级知识。
7. 在 Python OpenCV 寻找目标区域以及边缘扩展的解决方案
针对图像的特定区域进行操作,在 OpenCV 中被称作 ROI ,即目标区域或者叫做感兴趣区域,在处理图像的时候,可以先定位一个目标区域,然后再在该区域进行细节筛选,这样可以提高我们程序的速度和准确性。
实现 ROI 操作其实就是采用 numpy 对图像进行操作
例如下述测试代码,我们需要寻找图像指定区域
import cv2
import numpy as np
src = cv2.imread("./7_img.jpg")
# cv2.imshow("src",src)
cv2.imshow("src",src)
# 注意后面的列表获取,格式为 [rows,cols]
roi_img = src[50:150, 100:150]
print(roi_img.shape)
cv2.imshow("roi_img", roi_img)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果如下所示,尤其需要注意的是代码注释部分的说明,在做 ROI 的时候,需要筛选的区域用伪代码表示如下 src[起始行像素:结束行像素,起始列像素:结束列像素]
这个地方经常出现的一个 BUG 如下
error: (-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow'
很多博客中会写是图片文件中文路径的问题,但是其实这只是一种结果,真正的原因是图像出现了空结构,也就是读取图像的 shape
属性如果展示内容为 (0,0,3)
,那必然出现上述错误。例如下面代码就存在该问题。
import cv2
import numpy as np
src = cv2.imread("./7_img.jpg")
# cv2.imshow("src",src)
roi_img = src[50:50, 100:100]
print(roi_img.shape)
cv2.imshow("roi_img", roi_img)
cv2.waitKey()
cv2.destroyAllWindows()
确定目标区域,最大的难点就是坐标问题,你可以多次尝试一下,直到记住目标区域的定位方式。
获取到 ROI 区域之后,可以对其进行修改,例如,下述代码将 ROI 区域设置为灰度图像
import cv2
import numpy as np
src = cv2.imread("./7_img.jpg")
# cv2.imshow("src",src)
cv2.imshow("src", src)
# 注意后面的列表获取,格式为 [rows,cols]
roi_img = src[50:150, 100:150]
gray = cv2.cvtColor(roi_img, cv2.COLOR_BGR2GRAY)
src[50:150, 100:150] = gray
cv2.imshow("src", src)
cv2.waitKey()
cv2.destroyAllWindows()
直接运行该代码,会出现如下错误
ValueError: could not broadcast input array from shape (100,50) into shape (100,50,3)
因为合并的图像通道数不对,接下来你需要做的是将灰度图扩展为三通道形式,使用下述代码即可实现。
# 灰度图扩展到 3 通道
grays = np.stack((gray,)*3, axis=-1)
print(grays)
src[50:150, 100:150] = grays
其中用到了 numpy.stack(arrays, axis=0)
函数,将数组进行连接。修改代码之后得到的运行结果如下所示。
OopenCV 图像的拆分与合并
上述案例你已经掌握了图像目标区域获取的方式,接下来我们对图像进行一下通道的拆分与合并,具体会使用到两个函数,分别是 cv2.merge
和 cv2.split
。
两个函数的原型可以直接获取
# splite 函数原型
mv = cv2.split(m[, mv])
# merge 函数原型
dst = cv2.merge(mv[, dst])
下面进行图像的拆分,并通过 matplotlib
库进行图片的展示:
import cv2
import numpy as np
import matplotlib.pyplot as plt
src = cv2.imread("7_img.jpg")
b, g, r = cv2.split(src)
plt.subplot(131)
plt.imshow(b, "gray")
plt.title("b")
plt.subplot(132)
plt.imshow(g, "gray")
plt.title("g")
plt.subplot(133)
plt.imshow(r, "gray")
plt.title("r")
plt.show()
运行之后可以获取每个通道的灰度图,cv2.split
执行的效率并不高,所以你使用的图像如果过大,记得稍等片刻。
针对每个通道还可以进行拆分赋值,例如,你可以将 BGR 顺序颠倒,形成不同色彩的图片。
## 交换通道顺序,进行合并
dst = cv2.merge((r,g,b))
cv2.imshow("dst",dst)
cv2.waitKey()
运行之后,可以得到对应的效果。
cv2.merge
和 cv2.split
函数参数列表,请重点比对原型进行学习。
如果你想要单独修改某一通道值,可以使用 numpy 进行操作,例如我们将 R 通道的像素值修改为 0,使用下述代码即可
import cv2
import numpy as np
import matplotlib.pyplot as plt
src = cv2.imread("7_img.jpg")
src[:,:,2] = 0
cv2.imshow("src1",src)
src[:,:,2] = 255
cv2.imshow("src2",src)
cv2.waitKey()
OpenCV 图像边缘扩展
接下来将要学习的函数是图像扩边操作,使用 cv2.copyMakeBorder
函数,函数原型如下:
dst = cv2.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]])
先掌握几个核心参数 src
原图像,top
,bottom
,left
,right
分别表示在原图四周扩充边缘的大小。
关于 borderType
参数,表示的需要填充的边界类型,该值有多种取值,建议是自行尝试,我们采用其中一个优先进行说明。
import cv2
from matplotlib import pyplot as plt
src = cv2.imread("color.jpg")
# 后续绘图使用 pyplot ,所以切换一下颜色通道的排序,相当于从 BGR 转换为 RGB
b, g, r = cv2.split(src)
img = cv2.merge([r, g, b])
replicate = cv2.copyMakeBorder(img, 20, 20, 20, 20, cv2.BORDER_REPLICATE)
print("原图形状",src.shape)
print("扩充边界之后的形状",replicate.shape)
打印结果,注意像素的宽度和高度都扩展了 40
,扩展之后的图片,你可以自行比对。
原图形状 (624, 500, 3)
扩充边界之后的形状 (664, 540, 3)
图像扩展边界最后一个参数 borderType
有如下取值
cv2.BORDER_CONSTANT
:固定值填充;cv2.BORDER_REFLECT_101
或者cv2.BORDER_DEFAULT
:取镜像对称的像素填充;cv2.BORDER_REPLICATE
:重复最后一个像素;cv2.BORDER_WRAP
:取镜像。
结合上文,可以实现这样一个效果,找到 ROI 区域,然后对其进行边缘扩展。
import cv2
from matplotlib import pyplot as plt
src = cv2.imread("7_img.jpg")
# 后续绘图使用 pyplot ,所以切换一下颜色通道的排序,相当于从 BGR 转换为 RGB
b, g, r = cv2.split(src)
img = cv2.merge([r, g, b])
roi_img = img[120:170,200:250]
dst = cv2.copyMakeBorder(roi_img, 2, 2, 2, 2, cv2.BORDER_CONSTANT,value=[0,0,255])
img[118:172,198:252] = dst
plt.imshow(img)
plt.title('img')
plt.show()
执行代码之后,我们在原图找到某个区域,然后对其进行边缘扩展,实现了一个矩形的框选操作,效果如下:
- 分享
- 举报
-
浏览量:567次2023-12-21 10:38:07
-
浏览量:5126次2021-01-30 18:37:19
-
浏览量:6209次2021-02-01 17:50:45
-
浏览量:7567次2021-01-13 17:06:49
-
2020-12-12 22:07:09
-
浏览量:285次2023-08-02 20:35:16
-
浏览量:1801次2018-05-02 09:59:05
-
浏览量:1670次2019-12-11 15:43:39
-
浏览量:2165次2019-09-16 16:15:15
-
浏览量:3309次2020-12-03 14:16:32
-
浏览量:1651次2020-04-02 15:35:28
-
浏览量:1925次2019-12-27 15:14:01
-
浏览量:1144次2023-12-26 15:57:32
-
浏览量:500次2023-12-15 14:28:09
-
浏览量:1814次2019-10-09 14:42:49
-
浏览量:2050次2020-04-29 11:27:31
-
浏览量:1410次2022-10-20 17:13:08
-
浏览量:4698次2021-02-03 15:15:43
-
浏览量:811次2023-07-05 10:18:03
-
7篇
- DIY的一款好用的G711播放器+集赞赢大礼
- [python opencv 计算机视觉零基础到实战] 十七、深入ellipse方法
- OpenCV DNN C++ 使用 YOLO 模型推理
- 编译uboot 和 kernel
- 5. Python OpenCV 中滑动条详细说明与常见问题解决方案
- 海思hi3519av100上移植opencv3.4.1及移植成功验证
- [python opencv 计算机视觉零基础到实战] 十四 直方图颜色提鲜
- 计算机视觉图像处理-OpenCV入门基础学习
- 使用NLTK中的VADER模型进行数据的分析
- [python opencv 计算机视觉零基础到实战] 八、ROI泛洪填充
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
梦想橡皮擦
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明