基於opencv2實現證件照換背景(從藍色到紅色)

剛好手頭上有一張證件照,嘗試把藍色底換成紅色或白色底,網上搜的資料不多,且大多數都是基於opencv1寫的,於是嘗試寫了下opencv2的。主要步驟爲:

1.把RGB圖像轉換到HSV空間

2.取背景的一小塊20*20,計算藍色背景的平均色調和飽和度

3.設置閾值,取出藍色背景替換爲紅色背景

4.把HSV圖像轉換會RGB空間

5.濾波器去除邊緣效應

具體代碼爲:

// change_color.cpp : 定義控制檯應用程序的入口點。
//證件照從藍色底換成紅色底

#include "stdafx.h"
#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>

using namespace cv;
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	char *origin="Original";
	char *window="Image";
	char *str="D:\\jiangshan\\change_color\\IMG_1047.jpg";
	namedWindow(origin,1);
	namedWindow(window,1);
	Mat image=imread(str);
	if(!image.data)
	{
		cout<<"圖像載入出現問題"<<endl;
		return 0;
	}
	Mat roi=image(Rect(20,20,20,20));
	Mat hsvImg;
	cvtColor(image, hsvImg, CV_BGR2HSV); //將圖像轉換到HSV顏色空間
	//分離HSV空間,v[0]爲H色調,v[1]爲S飽和度,v[2]爲v灰度 
	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=SumH+roiH(i,j);*/
			SumH=int(roiH.at<uchar>(j,i))+SumH;
			SumS=int(roiS.at<uchar>(j,i))+SumS;
		}
	}
	avgH=SumH/400;
	avgS=SumS/400;
	//遍歷整個圖像
	int nl=hsvImg.rows;
	int nc=hsvImg.cols;
	int step=10;
	for(int j=0; j<nl; j++)
	{
		for(int i=0; i<nc; i++)
		{
			//以H.S兩個通道做閾值分割,把藍色替換成紅色
			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))
			{
				//cout<<int(v[0].at<uchar>(j,i))<<endl;
				v[0].at<uchar>(j,i)=0;
				/*cout<<int(v[0].at<uchar>(j,i))<<endl;*/
			}
		}
	}
	Mat finImg;
	merge(v,finImg);
	Mat rgbImg;
	cvtColor(finImg,rgbImg, CV_HSV2BGR); //將圖像轉換回RGB空間
	imshow(origin,image);
	imshow(window,rgbImg);
	//加個濾波把邊緣部分的值濾掉(此處應該用低通濾波器,但感覺不太好,還是不用了。)
	//Mat result;
	//GaussianBlur(rgbImg,result,Size(3,3),0.5);
	/*imshow(window,result);*/
	waitKey(0);
	//system("pause");
	return 0;
}


	////遍歷整個圖像
	//int nl=hsvImg.rows;
	//int nc=hsvImg.cols * hsvImg.channels();
	//for(int j=0; j<nl; j++)
	//{
	//	uchar *data=hsvImg.ptr<uchar>(j);
	//	for(int i=0; i<nc; i++)
	//	{
	//		cout<<int(data[i])<<" ";
	//	}
	//}

效果圖:


發佈了70 篇原創文章 · 獲贊 44 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章