ChromaKey

1.创建掩图(mask).

RGB值,用th来表示 -(g-(r+b))的值,然后我们寻找到某一个界点值k,当th的值大于k的时候表示src图上该点的是绿色,生成的mask图对应的位置就用黑色标定,当th的值小于k的时候表示src图不是绿色,那么mask图上对应位置的像素用白色来表示。在图形学中,我们常用黑色来表示背景,用白色来表示前景。

 

2.利用第一步生成好mask图,把src复制(copyTo)到一张新的背景图中,在新的背景图中只显示我们要扣出来的object。

   

3.因为在第一步生成mask也不是那么完美,可能还有某些绿色没有去掉,我们还需要再访问图片中每一个像素点,因为rgb图上绿色点的rgb的值是有范围的,那么我们就根据这个范围找出残留在图片上绿色的点,然后我们去掉该点。




#include<iostream>
#include<cv.h>
#include<highgui.h>
using namespace std;
using namespace cv;

//int main()
//{
// IplImage *src = 0;
// IplImage *histimg = 0;
// if ((src = cvLoadImage("screen.jpg", 0)) == NULL) // force to gray image
// return -1;
// cvNamedWindow("Histogram", 3); //创建直方图窗口
// histimg = cvCreateImage(cvGetSize(src), src->depth, 3);
// //改变背景色
// for (int h = 0; h < histimg->height; h++)
// {
// for (int w = 0; w < histimg->width * 3; w++)
// {
// ((uchar*)((int)histimg->imageData + histimg->widthStep*h))[w] = (uchar)125; //将背静改为白色
// }
// }
// cvShowImage("Histogram", histimg);
// cvWaitKey(0);
//}


int main()
{
Mat img = imread("foreground1.png");
//imshow("Lena Original", img);
for (int row = 0; row < img.rows; row++)
{
for (int col = 0; col < img.cols; col++)
{
/* 注意 Mat::at 函数是个模板函数, 需要指明参数类型, 因为这张图是具有红蓝绿三通道的图,
所以它的参数类型可以传递一个 Vec3b, 这是一个存放 3 个 uchar 数据的 Vec(向量). 这里
提供了索引重载, [2]表示的是返回第三个通道, 在这里是 Red 通道, 第一个通道(Blue)用[0]返回 */
if ( img.at<Vec3b>(row, col)[1]>140)
{if(img.at<Vec3b>(row, col)[0]<128)
if(img.at<Vec3b>(row, col)[2]<128)
{
img.at<Vec3b>(row, col)[0] = 255;
img.at<Vec3b>(row, col)[1] = 255;
img.at<Vec3b>(row, col)[2] = 255;
}
}
// else
// {
// img.at<Vec3b>(row, col)[0] = 0;
// img.at<Vec3b>(row, col)[1] = 0;
// img.at<Vec3b>(row, col)[2] = 0;
// }

}
}
imshow("result", img);
imwrite("result.png",img);

// cv::Mat result;
// result = imread("display1.bmp");
// cv::Mat forground= imread("screen.jpg",-1);
// //cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
// cv::Mat forground1(forground.size(),CV_8UC3,cv::Scalar(255,255,255));
// forground.copyTo(forground1,result); // bg pixels not copied
// cv::namedWindow("Segmented Image");
// cv::imshow("Segmented Image",forground1);
// cv::imwrite("foreground1.png",forground1);
cvWaitKey();
return 0;
}