分割分为两种
1 全自动图像分割:一般采用聚类算法来最大化前景与背景的差。
2 用户互动式图像分割:用户提供前景和背景的种子,然后对前景背景建立概率分布模型。
而GraphCut和GrabCut就是属于第二类图像分割算法。首先来说GraphCut。
Graph Cut(图形切割)应用于计算机视觉领域用来有效的解决各种低级计算机视觉问题,例如图像平滑(image smoothing)、立体应对问题(stereo correspondence problem)、图像分割(image segmentation)。
GraphCut利用最小割最大流算法进行图像的分割,可以将图像分割为前景和背景。使用该算法时需要在前景和背景处各画几笔作为输入,算法将建立各个像素点与前景背景相似度的赋权图,并通过求解最小切割区分前景和背景。
如果背景比较复杂或者背景和目标相似度很大,那分割就不太好了;二是速度有点慢。
我们的目标是一种通用的交互式分割技术,将图像分为两部分:“对象”和“背景”。用户通过指示绝对必须是对象一部分的某些像素(种子)和必须是背景一部分的某些像素,对分割施加某些硬约束。直观地说,这些硬约束提供了用户打算分段的线索。
Grab Cut只需要提供背景区域的像素集就可以了。也就是说你只需要框选目标,那么在方框外的像素全部当成背景
以下代码是给背景中的书画框框
"""
-*- coding: utf-8 -*-
author: Hao Hu
@date 2022/1/20 11:02 AM
"""
import cv2
import numpy as np
from matplotlib import pyplot as plt
import os.path as osp
WHITE = [255,255,255]
def grab_cut():
img_ori = cv2.imread('./sample10.jpg')
# 将img二值化
retVal, image = cv2.threshold(img_ori, 50, 100, cv2.THRESH_BINARY)
mask = np.zeros(image.shape[:2], np.uint8)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
ix = int(img_ori.shape[0] / 22)
iy = int(img_ori.shape[1] / 20)
w = iy * 20
h = ix * 22
rect = (ix, iy, int(w), int(h))
# cv2.rectangle(img, (ix*2, iy*3), (int(w*0.9), int(h*0.9)), (0, 255, 0), 2)
# 默认几个点作为物体和背景像素点
# (ix*15,iy*26),(ix*21,iy*15),(ix*21,iy*10)为背景像素点
cv2.circle(mask, (ix*15, iy*26), 15, [0,0,0], -1)
cv2.grabCut(image, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
mask2[ix * 21, iy * 19] = 1
#plt.imshow(mask2), plt.colorbar(), plt.show()
img = image * mask2[:, :, np.newaxis]
return img,mask2,img_ori
def get_three_RGB(mask):
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = list(contours)
contours.sort(key=lambda x: cv2.contourArea(x), reverse=True)
cnt = cv2.approxPolyDP(contours[0], epsilon=100, closed=True)
cnt = cv2.minAreaRect(cnt)
box = np.int0(cv2.boxPoints(cnt))
return mask, box
if __name__ == '__main__':
img,mask,img_ori = grab_cut()
_, box=get_three_RGB(mask)
re = cv2.drawContours(img_ori.copy(), [box], 0, (0, 255, 0), 3)
#cv2.imwrite(osp.join(save_p, osp.basename(im_p)), re)
plt.imshow(re), plt.show()