CV图像基本操作【2】——亮度对比度调整与背景相减(得前景)

2019-05-11  本文已影响0人  Mr_Relu

编程环境:

VS + OpenCV + C++
完整代码已经更新至GitHub,欢迎fork~GitHub链接


声明:创作不易,未经授权不得复制转载
statement:No reprinting without authorization


内容:

对比度及亮度的基本调整原理公式为:g(i,j) = af(i,j) + b*
->g 变换后图像
->f 变换前原图
->a 用于控制对比度
->b 用于控制亮度

1.1:对比度调整

       设计一个Sigmoid函数,实现对图像的对比度调整;使用opencv窗口系统的slider控件,交互改变Sigmoid函数的参数,实现不同程度的对比度调整;

1.2:背景相减

       对图像I和对应的背景图B,基于背景相减检测I中的前景区域,设法改进结果。

一、线性函数对比度亮度调节:

code
#include<opencv2/core/core.hpp>
#include<opencv2/imgcodecs.hpp>
#include<opencv2/core/saturate.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream> 

using namespace std;
using namespace cv;

int main(int, char** argv)
{
    double alpha = 1.0; /*< Simple contrast control */
    int beta = 0;       /*< Simple brightness control */

    Mat image = imread("a.png");
    //cvtColor(image, image, CV_BGR2GRAY);//转为灰度图
    Mat new_image = Mat::zeros(image.size(), image.type());

    cout << " Basic Linear Transforms " << endl;
    cout << "-------------------------" << endl;
    cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha;
    cout << "* Enter the beta value [0-100]: ";    cin >> beta;

    for (int y = 0; y < image.rows; y++) {
        for (int x = 0; x < image.cols; x++) {
            for (int c = 0; c < 3; c++) {
                new_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(alpha*(image.at<Vec3b>(y, x)[c]) + beta);
            }
        }
    }

    namedWindow("Original Image", WINDOW_AUTOSIZE);
    namedWindow("New Image", WINDOW_AUTOSIZE);

    imshow("Original Image", image);
    imshow("New Image", new_image);

    waitKey();
    return 0;
}

二、sigmoid函数对比度亮度调节:

image.png
(1)首先应用公式
image.png

(引用自论文A New Approach for Contrast Enhancement Using Sigmoid Function——Naglaa Hassan and Norio Akamatsul)对每个像素点进行处理,发现效果并不好,容易高亮丢失纹理(受参数C的影响太大),实用效果差如下图:


image.png
image.png
(2)自行设计调整函数:

t = I(x,y) / 255.00 * c_p * 0.1; //c_p为界面可动态调整参数
O(x,y) = I(x,y) ( ( 1.00/ ( 1.00+exp ( -t) ) + 0.5 ) + b_value - 100)
应用新公式测试效果如下:

image.png
(3)发现还是会有一些纹理丢失,思考后认为255/200-1<0.3,所以应该将0.5这个参数调低至0.3,调低为0.3后进行测试效果较好,达到预期效果。:
image.png
image.png
code:
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include<math.h>
#include <iostream>

using namespace std;
using namespace cv;

static void ContrastAndBright(int, void *);

int c_p;
int b_value;
Mat s_image, t_imag;

int main()
{
    s_image = imread("22.png");

    if (!s_image.data)
    {
        cout << "图片读取失败!" << endl;
        return false;
    }
    t_imag = Mat::zeros(s_image.size(), s_image.type());

    c_p = 20;
    b_value = 100;

    namedWindow("效果图窗口", WINDOW_AUTOSIZE);

    createTrackbar("对比度", "效果图窗口", &c_p, 200, ContrastAndBright);
    createTrackbar("亮  度", "效果图窗口", &b_value, 200, ContrastAndBright);

    ContrastAndBright(c_p, 0);
    ContrastAndBright(b_value, 0);

    waitKey(0);
    return 0;

}

static void ContrastAndBright(int, void *)
{

    namedWindow("窗口02", WINDOW_AUTOSIZE);
    // g_dstImage(i,j) =a*g_srcImage(i,j) + b

    for (int y = 0; y < s_image.rows; y++)
    {
        for (int x = 0; x < s_image.cols; x++)
        {
            for (int c = 0; c < 3; c++)
            {
                //0<=c_p<=200
                double t = ((s_image.at<Vec3b>(y, x)[c] - 127) / 225.00)*c_p*0.1;
                t_imag.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(s_image.at<Vec3b>(y, x)[c] * ((1.00 / (1.00 + exp(-t))) + 0.3) + b_value - 100);
                //int t = s_image.at<Vec3b>(y, x)[c];
                //t_imag.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(t * ((c_p*0.1 / (1.00 + exp(-t))) + 1));
            }
        }
    }
    imshow("窗口02", s_image);
    imshow("效果图窗口", t_imag);
}

三、背景相减实验:

1、相减得到图一,下半未很好显示,而后定义阈值后与(f_image(x,y)[c] - b_image(x,y)[c])比较,对RGB三通道分别赋值为0或255得到下图效果:
图一
图二(阈值=5)
图三(阈值=30)
图四(阈值=50)
2、调整改进算法,原理如下:

对于去除噪声点,可以考虑使用中指滤波,对椒盐噪声有较好效果

image.png
将像素点得RGB值看为一向量,求前景与背景三通道差值得平方和,最后取平方根后与阈值进行比较,大于阈值一并将三通道值都赋值为255,反之为0,最后效果如下:
50
75
100
150
可以看出当阈值为75-100时效果最好。
code
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include<math.h>
#include <iostream>

using namespace std;
using namespace cv;

int maind22(){
    Mat f_image, b_image;

    f_image = imread("123.png");
    b_image = imread("123b.png");

    //Mat gray_f;
    //cvtColor(f_image, gray_f, CV_BGR2GRAY);  //彩色图片转换成黑白图片



    if (!f_image.data||!b_image.data)
    {
        cout << "读取图片失败!" << endl;
        return -1;
    }

    if (f_image.rows != b_image.rows || f_image.cols != b_image.cols)
        cout << "前景图与后景图尺寸不符,无法相减!" << endl;

    Mat t_image = Mat::zeros(f_image.size(), f_image.type());

    namedWindow("<效果图窗口>", WINDOW_AUTOSIZE);

    double sum = 0.0;

    for (int y = 0; y < f_image.rows; y++)
    {
        for (int x = 0; x < f_image.cols; x++)
        {
            sum = 0.0;
            for (int c = 0; c < 3; c++)
            {
                sum += pow((f_image.at<Vec3b>(y, x)[c] - b_image.at<Vec3b>(y, x)[c]), 2);   
            }
            sum = sqrt(sum);
            if (sum >= 75) {
                for (int c = 0; c < 3; c++)
                {
                    t_image.at<Vec3b>(y, x)[c] = saturate_cast < uchar>(255);
                }
            }
            else {
                for (int c = 0; c < 3; c++)
                {
                    t_image.at<Vec3b>(y, x)[c] = saturate_cast < uchar>(0);
                }
            }               
        }
    }

    //cvtColor(t_image, t_image, CV_BGR2GRAY);
    imshow("<效果图窗口>", t_image);
    waitKey(0);
    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读