现需要对图像中的某区域进行颜色替换,效果如上图所示,左一为原图,中间位提取的紫色区域,右图为颜色替换结果,由于没有细致调参数所以效果表现不是很好,但是相关思路可以提供参考。代码如下:
#include
#include
#include
#include
#include
#define WINDOWS_NAME "混合图像"
using namespace std;
using namespace cv;
cv::Mat img1 = cv::imread("../TestChangeColor/test.jpg", 1);//
cv::Mat gray1,gray2,addWeightMat;
cv::Mat result2;
cv::Mat subMat= cv::Mat::zeros(img1.size(), CV_8UC1);
cv::Mat purpleMat;//二值图像
cv::Mat purpleToMorph;
int pThreshold = 80;
int pContrast = 12;
/*
* 1.检测紫色区域---->判断是否有紫色区域
* 2.提取紫色---->二值图像像素点位置
* 3.颜色替换---->输出替换图
*
* */
void onThresholdValueChange(int ,void* tempMat)
{
cv::Mat mat2 = *(cv::Mat*)tempMat;
cv::Mat mat1 = mat2.clone();
cv::Mat gray1;
cv::cvtColor(mat1,gray1,CV_BGR2GRAY);
for(int i = 0 ; i < img1.rows; i ++)
{
for(int j = 0 ; j < img1.cols; j ++)
{
if(purpleToMorph.at(i,j) == 255)
{
float alpha = gray1.at(i, j) - (float)pThreshold;
if(alpha < 0) alpha = 0;
// float b = mat1.at(i, j)[0];
float g = mat1.at(i, j)[1];
// float r = mat1.at(i, j)[2];
g *= 1 + (alpha / 256.0) * pContrast;
if(g > 255)
g = 255;
mat1.at(i, j)[1] = g;
}
}
}
imshow(WINDOWS_NAME,mat1);
}
void onContrastValueChange(int ,void* tempMat)
{
cv::Mat mat2 = *(cv::Mat*)tempMat;
cv::Mat mat1 = mat2.clone();
cv::Mat gray1;
cv::cvtColor(mat1,gray1,CV_BGR2GRAY);
for(int i = 0 ; i < mat1.rows; i ++)
{
for(int j = 0 ; j < mat1.cols; j ++)
{
if(purpleToMorph.at(i,j) == 255)
{
float alpha = gray1.at(i, j) - (float)pThreshold;
if(alpha < 0) alpha = 0;
// float b = mat1.at(i, j)[0];
float g = mat1.at(i, j)[1];
// float r = mat1.at(i, j)[2];
g *= 1 + (alpha / 256.0) * pContrast;
// g += 30 + (alpha / 100.0) * pContrast;
if(g > 255)
g = 255;
mat1.at(i, j)[1] = g;
}
}
}
imwrite("../TestChangeColor/result1.jpg",mat1);
imshow(WINDOWS_NAME,mat1);
}
void testChangeColor()
{
cv::resize(img1,img1,Size(400,400));
namedWindow("src",CV_WINDOW_AUTOSIZE);
imshow("src",img1);
cv::Mat baseMat = cv::Mat::zeros(img1.size(), CV_8UC3);
/*识别出紫色区域:RGB转HSV--->HSV空间能够非常直观的表达色彩的明暗,色调,以及鲜艳程度
*
* */
cv::Mat hsvMat;
cv::cvtColor(img1,hsvMat,CV_RGB2HSV);
cv::cvtColor(img1,gray1,CV_BGR2GRAY);
// imshow("hsv",hsvMat);
namedWindow("gray",CV_WINDOW_AUTOSIZE);
imshow("gray",gray1);
Scalar lowPurple = Scalar(110, 43, 46);//紫色对应的HSV最小值Scalar(125, 43, 46)
Scalar highPurple = Scalar(155, 255, 255);//紫色对应的HSV最大值(155, 255, 255)
cv::inRange(hsvMat,lowPurple,highPurple,purpleMat);
cv::Mat kernel = getStructuringElement(MORPH_RECT,Size(15,15),Point(-1,-1));
morphologyEx(purpleMat,purpleToMorph,MORPH_OPEN,kernel,Point(-1,-1));
cv::resize(purpleToMorph,purpleToMorph,Size(400,400));
namedWindow("purple",CV_WINDOW_AUTOSIZE);
imshow("purple",purpleToMorph);
/*
* int createTrackbar
* (
const string& trackerbarname, //创建滑动条的名字
const string winname, //所在窗口的名字
int* value, //一个指向整型的指针,表示滑块的位置,在创建时,滑块的初始位置就是该变量当前的值。
int count, //滑块可以达到的最大位置的值。滑块最小位置的值始终为0
TrackbarCallback onChange=0, //这个参数和回调函数有关,这是一个指向回调函数地址的指针,当滑动条上位置改变的时候,回调函数就会再次执行,
void* userdata=0//用户传给回调函数的数据,用来处理轨迹条事件。如果使用的value实参是全局变量,可以不去管userdata参数。
);
*/
namedWindow(WINDOWS_NAME,CV_WINDOW_AUTOSIZE);//createTrackbar之前定义才能出滑块
createTrackbar("Threshold Value",WINDOWS_NAME,&pThreshold,255,onThresholdValueChange,&img1);
onThresholdValueChange(pThreshold,&img1);
createTrackbar("Contrast Value",WINDOWS_NAME,&pContrast,255,onContrastValueChange,&img1);
onContrastValueChange(pContrast,&img1);
cv::waitKey(0);
}
int main(int argc, char *argv[])
{
testChangeColor();
return 0;
}
参考文献
[1] 【OpenCV】HSV颜色识别-HSV基本颜色分量范围
完整代码下载