OpenCV 任意曲线(S型等)调整图像色调,对比度小工具 C++

色调变换

改善图像色调的变换通常交互的选择。其概念是实验性的调整图像的亮度和对比度,以便在合适的灰度范围提供最多的细节。

彩色本身并不改变。在RGB和CMYK空间中,这意味着使用相同的变换函数映射3个(或4个)彩色分量。在HSI中则改进了亮度分量;

下面显示了3个常见的色调不平衡的几个典型变换----平淡的,较亮的,较暗的图像。

S型曲线可以增强对比度,凹凸曲线分别减小、增加亮度。

下图是S曲线调整后的效果:

OpenCV 任意曲线(S型等)调整图像色调,对比度小工具 C++

凹曲线降低亮度

OpenCV 任意曲线(S型等)调整图像色调,对比度小工具 C++OpenCV 任意曲线(S型等)调整图像色调,对比度小工具 C++

 

凸曲线增强亮度:

OpenCV 任意曲线(S型等)调整图像色调,对比度小工具 C++

单独修改RGB中的某一个通道,会改变色调;

R通道上凸,色调偏红;

OpenCV 任意曲线(S型等)调整图像色调,对比度小工具 C++

R通道下凹,色调偏青色(蓝绿色),相当于红色的补色;G 、B通道同理。

OpenCV 任意曲线(S型等)调整图像色调,对比度小工具 C++

 

代码实现:

 实现两个类,Curve 和 Curves 在文件Curves.cpp中

下面是主函数实现:

/*
 * test_Curves
 *
 *  Created on: 2019.03.21
 *      Author: cui
 */


#include <cstdio>
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "Curves.hpp"

using namespace std;
using namespace cv;

static string window_name = "Photo";
static Mat src;

static string curves_window = "Adjust Curves";
static Mat curves_mat;
static int channel = 0;
Curves  curves;

static void invalidate()
{
    curves.draw(curves_mat);
    imshow(curves_window, curves_mat);

    Mat dst;
    curves.adjust(src, dst);
    imshow(window_name, dst);

    int y, x;
    uchar *p;

    y = 150; x = 50;
    p = dst.ptr<uchar>(y) + x * 3;
    cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ")  ";

    y = 150; x = 220;
    p = dst.ptr<uchar>(y) + x * 3;
    cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ")  ";

    y = 150; x = 400;
    p = dst.ptr<uchar>(y) + x * 3;
    cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ")  " << endl;
}

static void callbackAdjustChannel(int , void *)
{
    switch (channel) {
    case 3:
        curves.CurrentChannel = &curves.BlueChannel;
        break;
    case 2:
        curves.CurrentChannel = &curves.GreenChannel;
        break;
    case 1:
        curves.CurrentChannel = &curves.RedChannel;
        break;
    default:
        curves.CurrentChannel = &curves.RGBChannel;
        break;
    }


    invalidate();
}

static void callbackMouseEvent(int mouseEvent, int x, int y, int flags, void* param)
{
    switch(mouseEvent) {
    case CV_EVENT_LBUTTONDOWN:
        curves.mouseDown(x, y);
        invalidate();
        break;
    case CV_EVENT_MOUSEMOVE:
        if ( curves.mouseMove(x, y) )
            invalidate();
        break;
    case CV_EVENT_LBUTTONUP:
        curves.mouseUp(x, y);
        invalidate();
        break;
    }
    return;
}


int main()
{
    //read image file
    src = imread("635c.tif");
    if ( !src.data ) {
        cout << "error read image" << endl;
        return -1;
    }
//    resize(src,src,Size(), 0.5,0.5);
    //create window
    namedWindow(window_name);
    imshow(window_name, src);

    //create Mat for curves
    curves_mat = Mat::ones(256, 256, CV_8UC3);

    //create window for curves
    namedWindow(curves_window);
    setMouseCallback(curves_window, callbackMouseEvent, NULL );
    createTrackbar("Channel", curves_window, &channel, 3, callbackAdjustChannel);


// 范例:用程序代码在Red通道中定义一条曲线
    curves.RGBChannel.clearPoints();
    curves.RGBChannel.addPoint( Point(0,  0) );
    curves.RGBChannel.addPoint( Point(64,  27) );
    curves.RGBChannel.addPoint( Point(127, 127) );
    curves.RGBChannel.addPoint( Point(192,  229) );
    curves.RGBChannel.addPoint( Point(256, 256) );

    invalidate();

    waitKey();

    return 0;

}

 

全部代码和测试图片下载地址:

https://download.****.net/download/cyf15238622067/11044921