【OpenCV-Python】25.OpenCV的交互式前景提取——示例1

25.OpenCV的交互式前景提取——示例



前言

  人工干预(体现交互)的方法将前景从图像中分割或提取出来。


一、使用模板匹配查找图像

# 使用模板匹配查找图像
img1 = cv2.imread('handball.jpg')                             	# 打开输入图像
temp = cv2.imread('ball.jpg')                                 	# 打开模板图像
cv2.imshow('original',img1)
cv2.imshow('template',temp)

img1gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY, dstCn=1)     	# 转换为单通道灰度图像
tempgray = cv2.cvtColor(temp, cv2.COLOR_BGR2GRAY, dstCn=1)     	# 转换为单通道灰度图像

h,w = tempgray.shape                                            # 获得模板图像的高度和宽度
res = cv2.matchTemplate(img1gray, tempgray, cv2.TM_SQDIFF)      # 执行匹配

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)         # 返回匹配位置
top_left = min_loc                                              # 最小值为最佳匹配,获得其位置
bottom_right = (top_left[0] + w, top_left[1] + h)               # 获得匹配范围的右下角位置

cv2.rectangle(img1, top_left, bottom_right, (0,0,255), 2)      	# 绘制匹配范围,红色边框

cv2.imshow('Detected Range',img1)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述


二、使用交互式前景提取方法分割图像

# 使用交互式前景提取方法分割图像 
img = cv2.imread('cup.jpg')
cv2.imshow('original',img)

mask = np.zeros(img.shape[:2], np.uint8)                 		# 定义原始掩模

bg = np.zeros((1,65),np.float64)
fg = np.zeros((1,65),np.float64)
rect = (50,50,200,300)                                   		# 根据原图设置包含前景的矩形大小

cv2.grabCut(img, mask, rect, bg, fg, 5, cv2.GC_INIT_WITH_RECT) 	# 第1次提取前景,矩形模式

imgmask = cv2.imread('cup2.jpg')                         		# 读取已标注的掩模图像
cv2.imshow('mask image',imgmask)

mask2 = cv2.cvtColor(imgmask,cv2.COLOR_BGR2GRAY,dstCn=1) 		# 转换未单通道灰度图像
mask[mask2 == 0] = 0                                     		# 根据掩模图像,将掩模图像中白黑色像素对应的原始掩模像素设置为0
mask[mask2 == 255] = 1                                   		# 根据掩模图像,将掩模图像中白色像素对应的原始掩模像素设置为1

cv2.grabCut(img, mask ,None, bg, fg, 5, cv2.GC_INIT_WITH_MASK) 	# 第2次提取前景,掩模模式

#将返回的掩模中像数值为0或2像素设置为0(确认为背景),
#所有1或3的像素设置为1(确认为前景)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')

img = img*mask2[:,:,np.newaxis]                           		# 将掩模与原图像相乘获得分割出来的前景图像

cv2.imshow('grabCut', img)                                		# 显示获得的前景
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述


三、使用鼠标选取范围的前景提取

# 鼠标事件的回调函数
def on_mouse(event, x, y, flag, param):        
    global rect
    global leftButtonDowm
    global leftButtonUp
    
    # 鼠标左键按下
    if event == cv2.EVENT_LBUTTONDOWN:
        rect[0] = x
        rect[2] = x
        rect[1] = y
        rect[3] = y
        leftButtonDowm = True
        leftButtonUp = False
        
    # 移动鼠标事件
    if event == cv2.EVENT_MOUSEMOVE:
        if leftButtonDowm and  not leftButtonUp:
            rect[2] = x
            rect[3] = y        
  
    # 鼠标左键松开
    if event == cv2.EVENT_LBUTTONUP:
        if leftButtonDowm and  not leftButtonUp:
            x_min = min(rect[0], rect[2])
            y_min = min(rect[1], rect[3])
            
            x_max = max(rect[0], rect[2])
            y_max = max(rect[1], rect[3])
            
            rect[0] = x_min
            rect[1] = y_min
            rect[2] = x_max
            rect[3] = y_max
            leftButtonDowm = False      
            leftButtonUp = True

# 读入图片
img = cv2.imread('hehua.jpg')
# 掩码图像,如果使用掩码进行初始化,那么mask保存初始化掩码信息;
# 在执行分割的时候,也可以将用户交互所设定的前景与背景保存到mask中,然后再传入grabCut函数;在处理结束之后,mask中会保存结果
mask = np.zeros(img.shape[:2],np.uint8)

# 背景模型,如果为None,函数内部会自动创建一个bgdModel;bgdModel必须是单通道浮点型图像,且行数只能为1,列数只能为13x5;
bgdModel = np.zeros((1,65),np.float64)

# 前景模型,如果为None,函数内部会自动创建一个fgdModel;fgdModel必须是单通道浮点型图像,且行数只能为1,列数只能为13x5;
fgdModel = np.zeros((1,65),np.float64)

#用于限定需要进行分割的图像范围,只有该矩形窗口内的图像部分才被处理;
rect = [0,0,0,0]  
    
#鼠标左键按下
leftButtonDowm = False
#鼠标左键松开
leftButtonUp = True
    
#指定窗口名来创建窗口
cv2.namedWindow('img', cv2.WINDOW_NORMAL) 
#设置鼠标事件回调函数 来获取鼠标输入
cv2.setMouseCallback('img',on_mouse)

#显示图片
cv2.imshow('img',img)


while cv2.waitKey(2) == -1:
    # 左键按下,画矩阵
    if leftButtonDowm and not leftButtonUp:  
        img_copy = img.copy()
        # 在img图像上,绘制矩形  线条颜色为green 线宽为2
        cv2.rectangle(img_copy,(rect[0],rect[1]),(rect[2],rect[3]),(0,255,0),5)  
        # 显示图片
        cv2.namedWindow('img', cv2.WINDOW_NORMAL) 
        cv2.imshow('img',img_copy)
        
    # 左键松开,矩形画好 
    elif not leftButtonDowm and leftButtonUp and rect[2] - rect[0] != 0 and rect[3] - rect[1] != 0:
        # 转换为宽度高度
        rect[2] = rect[2] - rect[0]
        rect[3] = rect[3] - rect[1]
        rect_copy = tuple(rect.copy())   
        rect = [0,0,0,0]
        
        #物体分割
        cv2.grabCut(img,mask,rect_copy,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
            
        mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
        img_show = img * mask2[:,:,np.newaxis]
        
        #显示图片分割后结果
        cv2.namedWindow('grabcut', cv2.WINDOW_NORMAL) 
        cv2.imshow('grabcut',img_show)
        #显示原图
        cv2.namedWindow('img', cv2.WINDOW_NORMAL) 
        cv2.imshow('img',img)    

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述


四、OpenCV-Python资源下载

OpenCV-Python测试用图片、中文官方文档、opencv-4.5.4源码


总结

  以上内容介绍了OpenCV-Python的交互式前景提取的相关示例,有关Python、数据科学、人工智能等文章后续会不定期发布,请大家多多关注,一键三连哟(●’◡’●)。

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器视觉小学徒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值