我们学习了前面几篇文章的那些函数的用法,就有了做这个小练习的基础。
这节课让我们一步一步一起实现一键换照片底色吧!
首先第一步,我们先要读取一张图片,在Opencv库中给我们定义了一个图片类型,我们先定义一个图片类型的变量来存储红底证件照
//导入照片
Mat img = imread("D:\\text.jpg");
imshow("img", img);
然后我们要先将图片转化为hsv格式,在之前的文章我们一起学习过函数cvtColor函数,该函数可以用来转化空间颜色(RGB->HSV)。
//转成hsv形式
Mat hsvimg;
cvtColor(img, hsvimg, COLOR_BGR2HSV);
imshow("2", hsvimg);
将照片转化成hsv格式以后我们可以使用inRange函数将hsv类型的图片进行二值化处理,将人物和背景进行分离,提取出人物。
**但要注意的是红色这个颜色比较特殊我们要将它分成两个区间然后再进行相加。
hsv的最小值和最大值参照下面这个表:
//将背景和人物进行分离
Mat tempimg;
Mat temp1;
Mat temp2;
//inRange(hsvimg, Scalar(0, 160, 165), Scalar(10, 255, 255), tempimg);
inRange(hsvimg, Scalar(0, 195, 195), Scalar(10, 255, 255), temp1);
inRange(hsvimg, Scalar(165, 205, 205), Scalar(180, 255, 255), temp2);
tempimg = temp1 + temp2;
imshow("tempimg", tempimg);
提取出人物后我们可以看见人物为黑(0),背景为白(255),但是我们的掩膜图像应该是将需要提取的图片信息变成白色,所以我们需要将图片进行”翻转“。
//将背景和人物黑白颠倒
bitwise_not(tempimg, tempimg);
imshow("4", tempimg);
然后我们需要创建一个与图片一样大小的蓝色背景图。
//创造一个蓝色背景
Mat blueback = Mat::zeros(img.size(), img.type());
blueback = Scalar(228, 155, 30);
imshow("5", blueback);
最后我们需要将提取出来的人物粘贴到蓝色背景图上
//将抠出来的人物粘贴到新的背景上
img.copyTo(blueback, tempimg);
imshow("blueback", blueback);
我们可以看见我们虽然完成了基本的换底色但是我们图片的边缘还是有一些红色的小瑕疵的,我们可以通过调节inRange里面的参数来消除一些,当然这样可能也会有一些不能消除,这就要我们学习一些图像处理的算法来解决该问题了。
后面附上具体源码供大家学习参考
//导入照片
Mat img = imread("D:\\text.jpg");
imshow("img", img);
//转成hsv形式
Mat hsvimg;
cvtColor(img, hsvimg, COLOR_BGR2HSV);
//imshow("2", hsvimg);
//将背景和人物进行分离
Mat tempimg;
Mat temp1;
Mat temp2;
//inRange(hsvimg, Scalar(0, 160, 165), Scalar(10, 255, 255), tempimg);
inRange(hsvimg, Scalar(0, 195, 195), Scalar(10, 255, 255), temp1);
inRange(hsvimg, Scalar(165, 205, 205), Scalar(180, 255, 255), temp2);
tempimg = temp1 + temp2;
//imshow("tempimg", tempimg);
//将背景和人物黑白颠倒
bitwise_not(tempimg, tempimg);
//imshow("4", tempimg);
//创造一个蓝色背景
Mat blueback = Mat::zeros(img.size(), img.type());
blueback = Scalar(228, 155, 30);
//imshow("5", blueback);
//将抠出来的人物粘贴到新的背景上
img.copyTo(blueback, tempimg);
imshow("blueback", blueback);