使用OpenCV的GrabCut实现勾轮廓抠图功能

圈轮廓

最近接了个抠图的功能,要求像这样子让用户把轮廓圈一下,把前景抠出来。这里用的是OpenCV的GrabCut算法。

void grabCut(InputArrayimg,InputOutputArraymask,Rectrect,InputOutputArraybgdModel,InputOutputArrayfgdModel,intiterCount,intmode=GC_EVAL)

Parameters:

img – Input 8-bit 3-channel image.

mask –Input/output 8-bit single-channel mask. The mask is initialized by the function when mode is set to GC_INIT_WITH_RECT. Its elements may have one of following values:

GC_BGD defines an obvious background pixels.

GC_FGD defines an obvious foreground (object) pixel.

GC_PR_BGD defines a possible background pixel.

GC_PR_FGD defines a possible foreground pixel.

rect – ROI containing a segmented object. The pixels outside of the ROI are marked as “obvious background”. The parameter is only used when mode==GC_INIT_WITH_RECT .

bgdModel – Temporary array for the background model. Do not modify it while you are processing the same image.

fgdModel – Temporary arrays for the foreground model. Do not modify it while you are processing the same image.

iterCount – Number of iterations the algorithm should make before returning the result. Note that the result can be refined with further calls with mode==GC_INIT_WITH_MASK or mode==GC_EVAL .

mode –Operation mode that could be one of the following:

GC_INIT_WITH_RECT The function initializes the state and the mask using the provided rectangle. After that it runs iterCount iterations of the algorithm.

GC_INIT_WITH_MASK The function initializes the state using the provided mask. Note that GC_INIT_WITH_RECT and GC_INIT_WITH_MASK can be combined. Then, all the pixels outside of the ROI are automatically initialized with GC_BGD .

GC_EVAL The value means that the algorithm should just resume.

传入的img是原图(CV_8UC3格式),mask是用户标记的前景和背景信息(矩阵中只含以上四种取值),rect是用户选中的感兴趣区域(ROI),bgdModel和fgdModel是临时数组(对同一张图片进行编辑时不要修改),iterCount是迭代次数,mode是运行模式(初始化或者不是初始化)。

总之,就是要用cv::GC_INIT_WITH_MASK模式去初始化,传入原图和用户圈出来的轮廓图。


mask

用户圈完轮廓之后,用cv::findContours()生成一张类似这样的图。轮廓外部标记为已知背景,轮廓内部标记为已知前景,轮廓标记为未知。

初始化完之后,将mask和1做与,然后将原图copyTo一下,就能得到抠出来的图片。

alphaMask = mask & 1;

src.copyTo(dst, alphaMask);


第一次运行结果

第一次出来的结果可能会有些地方没分好,这时候用户再手动标记一下,用cv::GC_EVAL继续运行就好了。

Win10的画图3D有个神奇选择功能,就是grabCut算法这个流程的,要先框出ROI,有兴趣的可以尝试一下。


你可能感兴趣的:(使用OpenCV的GrabCut实现勾轮廓抠图功能)