[python opencv 计算机视觉零基础到实战] 八、ROI泛洪填充

2021-01-14 17:20:07 浏览数 (2)

一、学习目标

  1. 了解什么是ROI
  2. 了解floodFill的使用方法

如有错误欢迎指出~

二、了解OpenCV中图像ROI的颜色填充

2.1 了解ROI是什么

ROI指的是region of Interest,翻译过来就是你所感兴趣的区域。弱在一张图片中,你感兴趣的是某一个区域,那么这个区域就可以称为ROI。我们通过一些方法选取了该区域后,可以进行操作;例如颜色填充、图像变换等编辑。

先有一张图如下:

我们对这张图的激光雕刻机部分感兴趣,那么就可以选取该部分。如何进行选取呢?我们可以通过代码得知该图片的大小:

代码语言:javascript复制
import cv2
img = cv2.imread(r"C:UsersAdministratorDesktop1.jpg")
print(img.shape)

得到该图片的高宽分别为447与755。

我们可以通过粗略的丈量得知激光雕刻机应在整个图片的正中央,那么宽应该为一半,大致在200到400之间;由于图片中激光雕刻机位于图片偏下部分,所以可以粗略得知高度在200至400之间。这时我们可以直接读取图片后获取指定的行列得到该区域图片。

代码语言:javascript复制
import cv2

img = cv2.imread(r'C:UsersAdministratorDesktop1.jpg')#读取
cv2.namedWindow("Image",cv2.WINDOW_NORMAL)#创建一个窗口
cv2.imshow("Image", img)#显示图像

roi=img[200:400,200:400]
cv2.imshow("roi", roi)#显示图像

cv2.waitKey (0)#等待关闭
cv2.destroyAllWindows()#destroy

以上代码读取图片后,通过选取图片区域进行ROI选择。img[200:400,200:400]代码中,第一个200:400指的是200指400行,第二个200:400指的是200至400列。通过两个选取的行与列的交叉区域则是所选择的ROI区域。图示如下,红色框框表示列,紫色框框表示行,其中重叠区域则是ROI选择区域。

以上代码在运行结果如下:

从结果中,我们可以知道,该值的列选择还应该往右边移动一部分,由于我们是200指400这个区域,那么我们现在应该移动的访问从图片上看,应该是接近300指500。修改代码。

代码语言:javascript复制
roi=img[200:400,280:450]

运行后最后得到如下结果:

我们得到ROI内容后,可以对该部分的内容进行编辑,例如转为灰度图像:

代码语言:javascript复制
gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray_roi", gray_roi)#显示图像

结果如下:

也可以将转换后的图片与原图进行结合,只需要将转换后的图片值对原图该区域的值进行替换即可,完整代码如下:

代码语言:javascript复制
import cv2

img = cv2.imread(r'C:UsersAdministratorDesktop1.jpg')#读取
cv2.namedWindow("Image",cv2.WINDOW_NORMAL)#创建一个窗口
cv2.imshow("Image", img)#显示图像

roi=img[200:400,280:450]
cv2.imshow("roi", roi)#显示图像

gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray_roi", gray_roi)#显示图像

gray_roi_rgb = cv2.cvtColor(gray_roi, cv2.COLOR_GRAY2BGR)#灰度图像转RGB
img[200:400,280:450]=gray_roi_rgb
cv2.imshow("Image2", img)#显示图像

cv2.waitKey (0)#等待关闭
cv2.destroyAllWindows()#destroy

在以上代码中需要注意的是,灰度图像必须转为RGB图形才能对原图进行赋值。以上代码中灰度转RGB图像的代码为:

代码语言:javascript复制
gray_roi_rgb = cv2.cvtColor(gray_roi, cv2.COLOR_GRAY2BGR)

最终运行结果如下:

2.2 泛洪填充及floodFill使用方法

泛洪填充指指定起始点,通过该像素点所链接的周围像素点在所指定的颜色值范围内进行颜色填充。该操作需要一个遮罩或者说掩膜进行运算处理。

首先我们依旧开始读取一张图像:

代码语言:javascript复制
import cv2
import numpy as np

img = cv2.imread(r"C:UsersAdministratorDesktop1.jpg")
cv2.imshow("img", img)

接着通过copy方法可以快速复制一张图片:

代码语言:javascript复制
copyimg = image.copy()

由于我们需要建立一个遮罩,这个遮罩跟原图片大小一致,所以代码可以写成如下:

代码语言:javascript复制
h, w = copyimg.shape[:2]
mask = np.zeros([h   2, w   2], np.uint8)

以上代码通过shape获取了原图片的高宽,接着通过zeros创建一个与原图大小一致的纯黑图片。那为什么要加2呢?因为接下来我们需要对图片进行颜色填充,官方的规定要 2,具体什么原因我本人没有进行深究,按照官方要求来就可以了。

那问题来了,遮罩是什么?还记得我们在逻辑运算应用那一个小节中,通过色彩提取后,可以得到目标对象的颜色范围,这个颜色范围是一张黑白图片,白色为选取的区域,黑色为不选取的区域,这时我们通过将提取出来的图片作为遮罩对图片进行bitwise_and运算,这时就可以还原出原本色彩,抠选出原图中的图像内容。其实遮罩的作用就是如此,我们通过zeros创建一张纯黑图片后,使用floodFill函数对指定目标进行填充;在填充之前,将进行一定的计算。由于floodFill函数将会选取出目标点,该目标点将作用在这张纯黑色的遮罩图片中,该纯黑图片将会对计算后选取的点进行指的变换,该区域就会变成白色,最终得到颜色填充的区域,进行填充。

我们首先看一下floodFill函数,floodFill函数接收7个参数,函数原型如下:

代码语言:javascript复制
floodFill(image, mask, seedPoint, newVal, loDiff=None, upDiff=None, flags=None)
  • image为传入的图像参数
  • mask为遮罩
  • seedPoint为选中的颜色填充的起始点
  • newVal填充的颜色像素值
  • loDiff选中起始点的颜色像素值的最低范围,例如是红色,那么红色减去该值后得到最低的取值范围
  • upDiff选中起始点的颜色像素值的最高范围,例如是红色,那么红色加该值后得到最高的取值范围
  • flags为CV_FLOODFILL_FIXED_RANGE或者CV_FLOODFILL_MASK_ONLY ,两者填充方式不一样,当前示例将讲解CV_FLOODFILL_FIXED_RANGE。若选择CV_FLOODFILL_FIXED_RANGE,则会比较像素点与其实像素点,若在颜色值的范围内,则进行填充。 此时我们调用floodFill方法,传入图片,遮罩,起始点,填充的颜色值,最低值,最高值与填充模式。
代码语言:javascript复制
cv2.floodFill(copyimg, mask, (220,420), (0, 255, 255), (5, 5, 5), (5, 5 ,5), cv2.FLOODFILL_FIXED_RANGE)

copyimg为图片;mask为遮罩;220,420为起始点;0, 255, 255为填充的颜色,为黄色;5, 5, 5为选中的起始点减去该颜色值,判断周围的颜色是否低于该值;5, 5 ,5为选中的起始点加上该颜色值,判断周围的颜色是否高于该值。最终的完整代码如下: img = cv2.imread(r"C:UsersAdministratorDesktop1.jpg") cv2.imshow(“img”, img)

在复制图像上进行操作

代码语言:javascript复制
import cv2
import numpy as np

img = cv2.imread(r"C:UsersAdministratorDesktop1.jpg")
cv2.imshow("img", img)
copyimg = img.copy()
h, w = copyimg.shape[:2]
mask = np.zeros([h   2, w   2], np.uint8)
cv2.floodFill(copyimg, mask, (220,420), (0, 255, 255), (5, 5, 5), (5, 5 ,5), cv2.FLOODFILL_FIXED_RANGE)
cv2.imshow("fill_color", copyimg)

cv2.waitKey (0)#等待关闭
cv2.destroyAllWindows()#destroy

运行结果如下:

我们现在可以证明220,420是否是起始点,我们可以换一个值,例如0,0。若在左上角进行颜色填充那么则判断正确:

我们也可以改变填充值的选择范围,将2个5,5,5改为50,50,50,可以明显看到效果:

代码语言:javascript复制
cv2.floodFill(copyimg, mask, (0,0), (0, 255, 255), (50,50, 50), (50, 50 ,50), cv2.FLOODFILL_FIXED_RANGE)

这时候的相关所链接的颜色范围扩大,那么所能填充的范围也肯定是扩大,运行结果如下:

其中颜色值可以可以进行修改,修改方法不再赘述。

三、总结

  1. 了解了ROI是感兴趣的选择范围
  2. 了解了ROI可以通过图片内容进行选择,并且可以与原图进行结合
  3. 了解了泛洪填充的方法
  4. 初步了解了mask遮罩以及floodFill函数的使用方法

0 人点赞