OpenCV学习(3)--证件照换底色、线性混合运算、增强图像对比度示例

证件照换底色

蓝色换红色效果不错,其他的不行

 1 // 照片换底色
 2 // 蓝色换为红色
 3 void red2Blue(cv::Mat& image, cv::Mat& rgbImage) {
 4     cv::Mat roi = image(cv::Rect(20, 20, 20, 20));  // cv::Rect() 参数表示矩形左上角和长宽信息
 5     cv::Mat hsvImage;
 6     cv::cvtColor(image, hsvImage, CV_BGR2HSV);  // 将图像转化为HSV颜色空间
 7     // 分离HSV空间 v[0]为H色调  v[1]为S饱和度  v[2]为v灰度
 8     vector<cv::Mat> v;
 9     cv::split(hsvImage, v);  // 多通道图像的分离
10     cv::Mat roiH = v[0](cv::Rect(20, 20, 20, 20));
11     cv::Mat roiS = v[1](cv::Rect(20, 20, 20, 20));
12     int sumH = 0;
13     int sumS = 0;
14     int avgH, avgS;   // 蓝底的平均色调和平均饱和度
15 
16     // 取一块蓝色背景 计算出他们的平均色调和平均饱和度
17     for (int i = 0; i < 20; i++) {
18         for (int j = 0; j < 20; j++) {
19             sumH = int(roiH.at<uchar>(j, i)) + sumH;
20             sumS = int(roiS.at<uchar>(j, i)) + sumS;
21         }
22     }
23 
24     avgH = sumH / 400;
25     avgS = sumS / 400;
26 
27     // 便利整个图像
28     int rows = hsvImage.rows;
29     int cols = hsvImage.cols;
30     int step = 10;
31 
32     for (int j = 0; j < rows; j++) {
33         for (int i = 0; i < cols; i++) {
34             // 以H和S两个通道做阈值分割 把蓝色替换成红色
35             if ((v[0].at<uchar>(j, i)) <= (avgH + 5) && (v[0].at<uchar>(j, i)) >= (avgH - 5)
36                 && (v[1].at<uchar>(j, i)) <= (avgS + 40) && (v[1].at<uchar>(j, i)) >= (avgH - 40)) {
37                 v[0].at<uchar>(j, i) = 0;
38             }
39         }
40     }
41 
42     cv::Mat finImage;
43     cv::merge(v, finImage);
44     //cv::Mat rgbImage;
45     cv::cvtColor(finImage, rgbImage, CV_HSV2BGR);  // 将图像转换回bgr空间
46     cv::imwrite("whiteMyself.jpg", rgbImage);  // 写入硬盘
47     cv::imshow("Res", rgbImage);
48 
49     cv::waitKey(0);
50     return;
51 }

采用同样的方式,更改参数,使得红底变为白底,效果极差

 1 int main(void) {   // 证件照换底色 简单的将指定颜色换成另外一个颜色 不行 即直接通过bgr的值来识别颜色并转换效果不好
 2     cv::Mat src = cv::imread("myself.jpg", cv::IMREAD_COLOR);
 3     //cv::Mat res;
 4 
 5     if (src.empty()) {
 6         std::cout << "Failed!" << std::endl;
 7         return 1;
 8     }
 9 
10     std::cout << "原图像!" << std::endl;
11     cv::namedWindow("Src", cv::WINDOW_AUTOSIZE);
12     cv::imshow("Src", src);
13     cv::waitKey(0);
14 
15     for (int r = 0; r < src.rows; r++) {
16         for (int c = 0; c < src.cols; c++) {
17             if (src.ptr<uchar>(r, c)[0] == 255 && src.ptr<uchar>(r, c)[0] == 0 && src.ptr<uchar>(r, c)[0] == 0) {  // bgr 蓝色
18                 // 蓝色替换成白色
19                 src.ptr<uchar>(r, c)[0] = 255;
20                 src.ptr<uchar>(r, c)[1] = 255;
21                 src.ptr<uchar>(r, c)[2] = 255;
22             }
23         }
24     }
25 
26     std::cout << "目标图像!" << std::endl;
27     cv::namedWindow("Res", cv::WINDOW_AUTOSIZE);
28     cv::imshow("Res", src);
29 
30     cv::waitKey(0);
31     return 0;
32 }

两图像的线性混合运算

 1 int mixTwoPictureExample(cv::Mat src1, cv::Mat src2, cv::Mat dst) {
 2     double alpha = 0.7;
 3     double beta;
 4 
 5     src1 = cv::imread("angel.jpg", cv::IMREAD_COLOR);
 6     src2 = cv::imread("sky.jpg", cv::IMREAD_COLOR);
 7 
 8     cv::Mat roi1(src1, cv::Rect(0, 0, 1500, 800));
 9     cv::Mat roi2(src2, cv::Rect(0, 0, 1500, 800));
10 
11     if (src1.empty())
12         std::cout << "Failed read angel!" << std::endl;
13 
14     if (src2.empty())
15         std::cout << "Failed read sky!" << std::endl;
16 
17     beta = 1.0 - alpha;
18 
19     // g(x) = f1(x)*a + f2(x)*(1 - a)
20     cv::addWeighted(roi1, alpha, roi2, beta, 0.0, dst);
21     // 注意图片roi1 roi2大小要一样 alpha beta分别表示再组合后的图像中roi1 roi2所占的权重
22     cv::namedWindow("Dst", cv::WINDOW_AUTOSIZE);
23     cv::imshow("Dst", dst);
24 
25     cv::waitKey(0);
26 
27     return 0;
28 }

增加图像对比度

 1 int changeContrastAndBrightnessExample(void) {
 2     // 改变图像的对比度和亮度
 3     // g(r, c) = a*f(r, c) + b  a b越大图像越亮
 4     double alpha = 1.0;  // 范围1.0-3.0
 5     int beta = 50;        // 范围0-100
 6 
 7     cv::Mat image = cv::imread("angel.jpg", cv::IMREAD_COLOR);
 8     // 初始化一个与原图像大小类型相同的模板
 9     cv::Mat image2 = cv::Mat::zeros(image.size(), image.type());
10 
11     for (int r = 0; r < image.rows; r++) {
12         for (int c = 0; c < image.cols; c++) {
13             // 3通道值 bgr
14             // cv::saturate_cast() 防溢出保护
15             image2.at<cv::Vec3b>(r, c)[0] = cv::saturate_cast<uchar>(alpha * (image.at<cv::Vec3b>(r, c)[0]) + beta);
16             image2.at<cv::Vec3b>(r, c)[1] = cv::saturate_cast<uchar>(alpha * (image.at<cv::Vec3b>(r, c)[1]) + beta);
17             image2.at<cv::Vec3b>(r, c)[2] = cv::saturate_cast<uchar>(alpha * (image.at<cv::Vec3b>(r, c)[2]) + beta);
18         }
19     }
20 
21     // 另外可以使用cv::Mat::convertTo()实现相同效果
22     // image.convertTo(image2, -1, alpha, beta);
23 
24     //cv::imshow("image", image);
25     //cv::imshow("image2", image2);
26 
27     //cv::waitKey(0);
28     return 0;
29 }

伽马矫正,放后面 

1 void gammaCorrectionExample() {
2 
3 }
原文地址:https://www.cnblogs.com/lnlin/p/13735724.html