项目功能实现:对一张白色背景的图片进行更换成蓝色背景,类似抠图更换背景操作
按照之前的博文结构来,这里就不在赘述了
一、头文件
inrange.h
#pragma once#include<opencv2/opencv.hpp>using namespace cv;class INRANGE{
public:void inrange(Mat& image);
};#pragma once
二、函数实现
inrange.cpp
函数实现思路:
首先定义三个Mat对象Mat,hsv, mask, blueback
hsv用于存储将原图转换到hsv空间中的像素信息
mask用于获取到图像主体数据信息
blueback为纯蓝色的背景,用于对原始图像更换背景
cvtColor(image,hsv,COLOR_BGR2HSV);
将原始的image图像转换到HSV色域中,得到图像hsv
inRange(hsv, Scalar(0, 0, 221), Scalar(180, 30, 255), mask);
通过参阅上述的HSV颜色分量范围表,得知白色所对应的hsv最小为(0,0,221),最大为(180,30,255),将hsv图像中的白色范围区域赋值给mask对象
此时mask是白色的背景保持不变,其他的人物主体变成了黑色
bitwise_not(mask, mask);
我们要的是人物主体,故通过取反操作将原先白色的背景变成黑色,黑色的人物主体变成白色,这样得到了人物主体是白色,其他都是黑色的图片
image.copyTo(blueback, mask);
将image对应的mask中像素值不为0的区域复制到blueback上
#include"inrange.h"
#include<iostream>
#include<opencv2/opencv.hpp>void INRANGE::inrange(Mat& image) {Mat hsv, mask, blueback;cvtColor(image,hsv,COLOR_BGR2HSV);//将RGB色域的图像通过cvtColor函数转换到HSV色域中来inRange(hsv, Scalar(0, 0, 221), Scalar(180, 30, 255), mask);//将hsv图像的白色范围像素点提取为mask//此时的mask为只保留白色区域的图片,区域的颜色都为黑色/*inRange函数:提取指定色差范围区域的颜色在相应的HSV表中,白色的最小值为(0,0,211),最大值为(180,30,255)*/imshow("mask_origin", mask);//最终的观察效果为:beyond成员是黑色的,其他白色背景均正常显示blueback = Mat::zeros(image.size(), image.type());blueback = Scalar(255, 0, 0);//生成一张与原图大小一样的蓝色图片(B,G,R)imshow("blueback", blueback);bitwise_not(mask, mask);//我们的目的是要把beyond四子给抠出来换个背景,故需要取反,将原先黑色的四子转换为白色的imshow("mask_not", mask);//取反之后,四子变成了白色255,原先的背景变成了黑色0image.copyTo(blueback, mask);imshow("ROI区域提取", blueback);//最终在全蓝的blueback图片中,把对应的四子给拷贝了过去
}
三、主函数
yy_main.cpp
#include <opencv2/opencv.hpp>
#include <iostream>
#include "inrange.h"using namespace cv;
using namespace std;int main(int argc, char** argv) {Mat src = cv::imread("E:/C++_workspace/beyond.jpg", IMREAD_COLOR);if (src.empty()) {printf("load image is false...\n");return -1;}namedWindow("yanyu", WINDOW_FREERATIO);imshow("yanyu", src);INRANGE yy;yy.inrange(src);waitKey(0);destroyAllWindows();return 0;
}
项目结构如下:
运行效果如下:
这里因为原图中贯中额头反光、家驹项链为白色等情况导致处理结果不太理想