文章目录
一、前言
在上一章,我们学习了多种常用的图像编辑算法。接下来,我们将探讨如何利用OpenCV实现图像提取。本文旨在深入探讨如何高效提取图像ROI(Region of Interest,感兴趣区域)的技术。我们将从ROI的基础概念出发,详细介绍如何通过鼠标操作、图像处理技术以及编程实践,在Python中使用OpenCV库精准提取图像中的特定区域。
二、图像提取
ROI(Region of Interest,感兴趣区域)是指图像中用户特别关注或需要进行进一步处理的区域。它通常是一个矩形、圆形或其他形状的区域,包含了图像分析或识别任务中最重要的信息。在图像处理和计算机视觉领域,ROI的提取和使用可以显著提高处理效率,减少计算资源的浪费,并帮助聚焦于图像中最相关的部分。
2.1 cv2.bitwise_and()提取roi区域
一种简单的提取方法是使用图像和掩模的按位操作。在这里,我们采用的是OpenCV库中的cv2.bitwise_and()函数。这个函数能够有效地将掩模与原图像相结合,只保留掩模中白色区域对应的原图像部分,从而实现前景的精确提取。
函数说明:
图像的与运算主要用于获取某个图像中感兴趣的部分,是针对两个图像矩阵数组或一个数组与标量的按位与可以理解为两张图像取一个交集其函数为:bitwise_and(src1, src2, dst=None, mask=None)
参数说明:
src1、src2:为输入图像或标量,标量可以为单个数值或一个四元组
dst:可选输出变量,如果需要使用非None则要先定义,且其大小与输入变量相同
mask:图像掩膜,可选参数,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0
例子:
import cv2
import numpy as np
img1 = cv2.resize(cv2.imread(r"D:\pythonProject\1.jpg", flags=1),(512,512))# 读取图像并转化为512*512大小
b,g,r = cv2.split(img1)# 将图像通道进行划分
value,th_image=cv2.threshold(b,140,255,cv2.THRESH_BINARY)# 图像二值化,将大于140像素值的点置为255 小于的点置为0
contours, _ = cv2.findContours(th_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)# 查找轮廓
mask = th_image.copy()# 制作mask
area =[]# 将所有检出的轮廓放置在area列表中for k inrange(len(contours)):
area.append(cv2.contourArea(contours[k]))#
max_idx = np.argmax(np.array(area))# 返回最大索引的坐标
mask = cv2.drawContours(mask, contours, max_idx,255, cv2.FILLED)# 填充最大的轮廓
area = cv2.bitwise_and(img1,img1,mask=mask)
cv2.imshow("mask",mask)
cv2.imshow("area",area)
cv2.waitKey(0)
cv2.destroyAllWindows()# 释放所有窗口
效果:
以此我们就可以将橘子切面进行切割出来,但可以看出还有许多无用的离散特征,这些特征等我们后续讲图像降噪和图像形态学变换的时候可以进行筛除,处理后就可以获得一个干净的橘子切面了获取完切面.
2.2 鼠标框选roi区域:
OpenCV能够捕捉鼠标和键盘动作,通过编写代码可以截取鼠标选中的区域供后续处理。在OpenCV读取的图像窗口中,可以通过鼠标操作来实现多种功能,如获取点击位置的坐标、颜色,或在点击点绘制圆等。下面将介绍如何通过点击鼠标左键确定图像左上角端点,拖拽鼠标来框选ROI区域,并在松开左键时保存该图像区域。
我们可以通过调用cv2.setMouseCallback(winname, callback, userdata)函数来获取鼠标事件的状态。该函数接受三个参数:winname、callback和userdata。第一个参数winname是窗口名称,通常是通过cv2.namedWindow(‘image’)创建的图像窗口,例如这里的窗口名就是’image’。第二个参数callback是一个回调函数,你可以在其中定义鼠标事件的处理逻辑。至于第三个参数userdata,它是传递给回调函数的额外数据。
接下来,详细介绍一下回调函数。回调函数是用户自定义的,但需要遵循一定的格式。你可以随意命名这个函数,但通常它应该包含五个参数,例如on_mouse(event, x, y, flags, userdata)。这五个参数分别代表鼠标事件类型、鼠标点击的x坐标、y坐标、鼠标事件的标志以及前面提到的userdata。
函数说明:
enent:鼠标事件,x:横坐标,y:纵坐标,flags:事件组合
在cv2.setMouseCallback函数中,userdata参数用于传递用户定义的数据,它会被传递到回调函数on_mouse中。flags参数代表鼠标事件的组合位,如果需要同时处理多个鼠标动作,可以通过将flags与特定的鼠标事件标志进行位与操作(AND operation)来实现。x和y参数分别表示当前鼠标所在位置的横坐标和纵坐标。event参数则表示发生的鼠标事件,目前OpenCV支持以下几种鼠标事件:
EVENT_MOUSEMOVE 鼠标移动
EVENT_LBUTTONDOWN 左键按下
EVENT_RBUTTONDOWN 右键按下
EVENT_MBUTTONDOWN 滚轮按下
EVENT_LBUTTONUP 左键抬起
EVENT_RBUTTONUP 右键抬起
EVENT_MBUTTONUP 滚轮抬起
EVENT_LBUTTONDBLCLK 左键双击
EVENT_RBUTTONDBLCLK 右键双击
EVENT_MBUTTONDBLCLK 中间双击
EVENT_FLAG_LBUTTON 左键拖拽
EVENT_FLAG_RBUTTON 右键拖拽
EVENT_FLAG_MBUTTON 中键拖拽
EVENT_FLAG_CTRLKEY 按住ctrl不放
EVENT_FLAG_SHIFTKEY 按住shift不放
EVENT_FLAG_ALTKEY 按住alt不放
可根据具体需求进行选择
例子:
import cv2
defon_mouse(event, x, y, flags, param):
img = cv2.imread(r"D:\pythonProject\1.jpg")
cv2.imshow("image", img)#显示图片在"image"窗口上
img2 = img.copy()if event == cv2.EVENT_LBUTTONDOWN:#左键点击
param.append(x)
param.append(y)#添加当前点并存储在point中
cv2.circle(img2,tuple(param),10,(0,255,0),5)#在点上画个圆增强显示效果
cv2.imshow('image', img2)elif event == cv2.EVENT_MOUSEMOVE and(flags & cv2.EVENT_FLAG_LBUTTON):#移动鼠标,左键拖拽
cv2.rectangle(img2,tuple(param),(x,y),(255,0,0),15)#需要确定的就是矩形的两个点(左上角与右下角),颜色红色,线的类型(不设置就默认)。
cv2.imshow('image', img2)elif event == cv2.EVENT_LBUTTONUP:#左键释放
point2 =(x,y)
cv2.rectangle(img2,tuple(param), point2,(0,0,255),5)#需要确定的就是矩形的两个点(左上角与右下角),颜色蓝色,线的类型(不设置就默认)。
cv2.imshow('image', img2)
min_x =min(tuple(param)[0],point2[0])#取出左上点和松手时鼠标位置点中的最小的x,y坐标
min_y =min(tuple(param)[1],point2[1])
width =abs(tuple(param)[0]-point2[0])#算出矩形框长宽
height =abs(tuple(param)[1]-point2[1])
cut_img = img[min_y:min_y+height, min_x:min_x+width]
cv2.imshow("crop",cut_img)
cv2.imwrite('./crop_image.jpg', cut_img)#将切割后的图像保存defmain():
point=[]# 右上角的点的存储列表
cv2.namedWindow('image')# 创建图像窗口窗口名字为image
cv2.setMouseCallback('image',on_mouse,point)
cv2.waitKey(0)if __name__=='__main__':
main()
上述代码实现了以下四个功能:
这段代码实现了一个图像处理功能,具体如下:
1.定义了一个回调函数on_mouse,它将在不同的鼠标事件发生时被调用。
当鼠标左键在图像窗口上点击时(EVENT_LBUTTONDOWN),会在点击的位置画一个绿色的圆,并将点击位置的坐标(x, y)添加到param列表中。
2.当鼠标在图像窗口上移动并且左键被按下时(EVENT_MOUSEMOVE与EVENT_FLAG_LBUTTON),会在图像上绘制一个红色的矩形框,矩形的起始点是之前左键点击的位置,当前鼠标位置是矩形的终点。
3.当鼠标左键释放时(EVENT_LBUTTONUP),会在图像上绘制一个蓝色的矩形框,这个矩形框的起始点是之前左键点击的位置,终点是左键释放时的位置。然后计算矩形框的左上角坐标和长宽,并从原图中裁剪出这个矩形框内的图像区域。
4.裁剪出的图像区域会显示在一个新的窗口中,标题为"crop",并且会被保存为文件crop_image.jpg。
最后,程序进入一个无限循环,等待键盘输入,直到用户按下任意键退出。
总结
在这篇博客中,我们学习了如何使用OpenCV库在Python中提取图像的ROI(感兴趣区域)。文章简洁明了地讲解了ROI的重要性,并展示了如何通过制作黑白掩模来精准定位和提取所需图像部分,同时排除无关背景。我们介绍了cv2.bitwise_and()函数的应用,以及如何通过鼠标操作来手动选择ROI。通过这篇博客,读者能够轻松掌握图像处理的这一关键技能,为后续的视觉应用打下坚实的基础。
版权归原作者 CV-King 所有, 如有侵权,请联系我们删除。