本節(jié)重點(diǎn)
實(shí)際情況下熔任,輪廓圖由于背景的干擾泽本,常常導(dǎo)致制作出的詞云往往輪廓不突出染突,致使詞云效果差捻爷。本節(jié)利用opencv中的前景提取函數(shù)grabCut(),來(lái)制作背景為白色的前景輪廓提取圖份企。
grabCut()有兩種模式:1. 認(rèn)為劃定邊界框也榄,邊界外部被認(rèn)定為背景(RECT模式);2. 手動(dòng)標(biāo)定背景與前景,依據(jù)標(biāo)定的內(nèi)容來(lái)提取(MASK模式)甜紫。
第一種模式來(lái)獲取前景:
這種模式下降宅,需要手動(dòng)單擊左鍵來(lái)框選前景區(qū)域。
# 利用矩形框來(lái)選中前景區(qū)囚霸,矩形外部為背景區(qū)域
import numpy as np
import cv2
from matplotlib import pyplot as plt
#獲取圖片
img = cv2.imread('zende.jpg')
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
#根據(jù)鼠標(biāo)事件來(lái)劃定邊界框
def drawRect(event,x,y,flags,param):
global ix,iy,X,Y,W,H,img
#若鼠標(biāo)左鍵按下腰根,則記住當(dāng)前位置,邊界框的一個(gè)頂點(diǎn)
if event==cv2.EVENT_LBUTTONDOWN:
ix,iy=x,y
#拖動(dòng)的過(guò)程中拓型,對(duì)原圖的復(fù)制體畫(huà)矩形额嘿,img_temp表示臨時(shí)使用圖片
elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
img_temp=img.copy()
cv2.rectangle(img_temp,(ix,iy),(x,y),(0,255,25),1)
cv2.imshow('rect_test',img_temp)
#當(dāng)鼠標(biāo)左鍵釋放,則將當(dāng)前位置作為邊界框的另一個(gè)頂點(diǎn)
elif event==cv2.EVENT_LBUTTONUP:
X=min(ix,x)
Y=min(iy,y)
W=max(ix,x)-X
H=max(iy,y)-Y
#使用grabCut()的RECT模式來(lái)提取前景
cv2.grabCut(img,mask,(X,Y,W,H),bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img=img*mask2[:,:,np.newaxis]
img += 255*(1-cv2.cvtColor(mask2,cv2.COLOR_GRAY2BGR))
cv2.imwrite('test_method1.jpg',img)
cv2.imshow('rect_test',img)
ix,iy,X,Y,W,H=[0]*6
cv2.namedWindow('rect_test')
cv2.setMouseCallback('rect_test',drawRect)
cv2.imshow('mask',mask)
cv2.imshow('rect_test',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
處理效果:
(左)原圖 (右)RECT模式下提取結(jié)果
優(yōu)點(diǎn):提取過(guò)程簡(jiǎn)單,整體效果不錯(cuò)劣挫,對(duì)人物頭發(fā)邊緣册养、裙角提取得到位;不足:人物:發(fā)帶的處理压固,人物外:蝴蝶球拦,月亮(不完整)等細(xì)節(jié)很容易就被判為背景,無(wú)法控制邓夕。
第二種模式來(lái)獲取前景:
這種模式下刘莹,需要畫(huà)出前景和背景阎毅,再依據(jù)效果來(lái)調(diào)整焚刚。
#利用掩模圖來(lái)實(shí)現(xiàn)前景區(qū)的提取
import numpy as np
import cv2
# mode來(lái)決定當(dāng)前畫(huà)前景還是背景,前景時(shí)畫(huà)筆為白色扇调,畫(huà)背景時(shí)畫(huà)筆為黑色矿咕,默認(rèn)畫(huà)筆為白色
mode=True
#函數(shù)用來(lái)選定前景和背景,實(shí)質(zhì)是移動(dòng)鼠標(biāo)過(guò)程中畫(huà)圓
def drawCircle(event,x,y,flags,param):
global img_temp,mask1
if event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
if mode:
color_used=1
else:
color_used=0
cv2.circle(img_temp,(x,y),5,(255*color_used,)*3,-1)
cv2.circle(mask1,(x,y),3,color_used,-1)
cv2.imshow('img',img_temp)
# cv2.imshow('draw_test',mask1)
cv2.namedWindow('img')
img = cv2.imread('zende.jpg')
img_temp=img.copy()
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
mask1=3*np.ones(img.shape[:2],np.uint8)
cv2.setMouseCallback('img',drawCircle)
cv2.imshow('img',img)
#cv2.imshow('draw_test',mask1)
# 按下'm'鍵表示切換畫(huà)筆模式狼钮,按下'q'鍵退出碳柱,按下'o'鍵表示選定完畢開(kāi)始提取
while(1):
k=cv2.waitKey(0)& 0xFF
if k==ord('m'):
mode=not mode
elif k==ord('q'):
break
elif k==ord('o'):
cv2.grabCut(img,mask1,None,bgdModel,fgdModel,4,cv2.GC_INIT_WITH_MASK)
mask2 = np.where((mask1==2)|(mask1==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
img += 255*(1-cv2.cvtColor(mask2,cv2.COLOR_GRAY2BGR))
cv2.imwrite('test.jpg',img)
cv2.imshow('img',img)
cv2.destroyAllWindows()
處理效果:
處理過(guò)程(左) MASK模式下處理結(jié)果(右)