主要步骤为:
1. 把 RGB 图像转换到 HSV 空间
2. 取背景的一小块 20*20,计算蓝色背景的平均色调和饱和度
3. 设置阈值,取出蓝色背景替换为红色背景
4. 把 HSV 图像转换会 RGB 空间
5. 滤波器去除边缘效应
具体代码为:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
const char* origin = "original";
const char* window = "image";
const char* str = "image.jpg";
Mat image = imread(str);
if (!image.data)
{
cout<<"image not load...."<<endl;
return -1;
}
//imshow(origin,image);
Mat roi = image(Rect(20,20,20,20));
Mat hsvImg;
cvtColor(image,hsvImg,CV_BGR2HSV);
//色调 饱和度 灰度
vector<Mat>v;
split(hsvImg,v);
Mat roiH = v[0](Rect(20,20,20,20));
Mat roiS = v[1](Rect(20,20,20,20));
int sumH = 0;
int sumS = 0;
int avgH,avgS;//蓝底的平均色调和平均饱和度
//取一块蓝色背景,计算平均色调和饱和度
for (int i = 0;i<20;i++)
{
for (int j = 0;j<20;j++)
{
sumH = int(roiH.at<uchar>(j,i))+sumH; //统计感兴趣区域的总像素
sumS = int(roiS.at<uchar>(j,i))+sumS;
}
}
avgH = sumH /400;
avgS = sumS /400;
//遍历整个图像
int Row = hsvImg.rows;
int Col = hsvImg.cols;
int step = 10;
for (int i =0;i<Row;i++)
{
for (int j = 0;j<Col;j++)
{
//以HS两个通道做阈值分割,把蓝色替换成红色
if (v[0].at<uchar>(j,i)<=(avgH+5) && v[0].at<uchar>(j,i)>=(avgH-5) &&
v[1].at<uchar>(j,i)<=(avgS+40) && v[1].at<uchar>(j,i)>=(avgS-40))
{
//满足阈值范围的即为背景
v[0].at<uchar>(j,i) = 0;//红色背景
}
}
}
Mat finImg;
merge(v,finImg);
Mat rgbImg;
cvtColor(finImg,rgbImg,CV_HSV2BGR);
imshow(origin,image);
imshow(window,rgbImg);
Mat result;
GaussianBlur(rgbImg,result,Size(3,3),0.5);
imshow("result",result);
waitKey(0);
return 0;
}
运行效果: