OpenCV抠图的正确姿势
利用OpenCV官方算法进行前景识别,达成证件照抠图的效果
一、开篇
一位靓丽的姑姑:
出于某种目的,我们打算去掉图中的背景,除开PhotoShop,可以直接使用OpenCV库,用如下的代码完成这个任务:
二、代码实例
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>//resize
#include <opencv2/core/types.hpp>//rect
using namespace cv;
int mian(){
/* 读取图像文件 */
Mat human = imread("D:\\human.jpg");
/* 按算法需求准备几个Mat对象 */
Mat dstxx(human);
Mat fgmodel, bgmodel;
/* 初步选定人像区域 可以调整 */
int topx = human.cols / 4;
int topy = 0;
int bottomx = human.cols * 3 / 4;
int bottomy = human.rows;
cv::Rect rectangle(topx,topy,bottomx,bottomy);
/* 使用grabCut算法标记像素点 */
cv::grabCut(human, //图像
dstxx, //标记后的像素矩阵
rectangle, //初步选定的人像区域
bgmodel, //算法要求的矩阵
fgmodel, //算法要求的矩阵
6, //算法迭代次数
cv::GC_INIT_WITH_RECT //使用矩形模型进行标记
);
/* 取出人像区域的标记,还是存到dstxx中 */
cv::compare(dstxx,cv::GC_PR_FGD,dstxx,cv::CMP_EQ);
/* 准备存储人像数据的矩阵 */
cv::Mat foreground(human.size(),CV_8U);
/* 复制人像区域的数据到foreground中 */
human.copyTo(foreground,dstxx);
/* 展示结果和原图 */
imshow("foreground", foreground);
imshow("source",human);
waitKey(0);
}
三、测试及结果
结果如下,还不错:
换一张桃乃木香奈的
调整参数:
int topx = human.cols / 5;
int topy = 0;
int bottomx = human.cols * 2 / 3;
int bottomy = human.rows * 3 / 4;
cv::Rect rectangle(topx,topy,bottomx,bottomy);
看看结果:
四、参考资料
把几个函数的说明内容搬过来啦,需要的自取
1、cv::Compare()
2、cv::grabCut()
3、cv::Mat:CopyTo()