• OpenCV实现Photoshop算法(四): 色阶调整


    色阶调整( Levles Adjustment )

    (一)色阶调整原理

    色阶是什么:色阶就是用直方图描述出的整张图片的明暗信息。如图

    从左至右是从暗到亮的像素分布,黑色三角代表最暗地方(纯黑),白色三角代表最亮地方(纯白)。灰色三角代表中间调。

    每一个色阶定义有两组值:

    一组是输入色阶值,包含黑灰白三个值, 上图中: 黑点值为0, 灰点为1.00,白点为255

    另一组是输入色阶值,包含黑白两个值,上图中:输出色阶黑为0,白为255

    对于一个RGB图像,  可以对R,  G,  B 通道进行独立的色阶调整,即,对三个通道分别使用三个色阶定义值。还可以再对 三个通道进行整体色阶调整。 因此,对一个图像,可以用四次色阶调整。最终的结果,是四次调整后合并产生的结果。

    我们先来分析对单通道的色阶原理,比如:对红色通道定义色阶调整如下:

    则此时:  输入色阶值为: 黑13,   灰1.29,    白240,   输出色阶值为:黑11,白242

    则色阶调整的实现是: 当输入值<黑点值(13)时,全部变为输出色阶的黑值。 当输入值>白点(240)时,全部变为输出色阶的白值

    当输入值介于黑值与白值之间(13-240)时,则结合灰度系数,按比例重新计算,变为一个新的值。

    对红、绿、蓝三个独立通道调整方式都与上述算法相同。各通道调整是互不相关的。

    对RGB通道进行整体调整时,则对RGB三个值进行同时变换。

    (二)色阶调整的OpenCV实现

    我用opencv写了两个 C++ 类: Levels类实现了多通道的色阶的定义、实施调整。  Level类是一个通道的色阶定义类。

    源码共两个文件:    Levels.hpp,  Levels.cpp

    源码有一定的长度,不具体解释了,请见注释。

    补充说明几点:

    1, Levels类中定义了四个Level对象(即四个通道),分别是RedChannel, GreenChannel, BlueChannel 和 RGBChannel.

    2,每个Level对象有五个属性值:

    1 int   Shadow;  //输入色阶黑点值
    2 float Midtones; //输入色阶灰点值(注意是浮点数)
    3 int   Highlight; //输入色阶白点值
    4 int   OutputShadow; //输出色阶黑点值
    5 int   OutputHighlight; //输出色阶白点值

    3, 使用方法:创建一个Levels对象,然后对其所属的Level对象的属性值进行赋值,然后调整 Levels类的adjust()方法,即可实现色阶调整。

    (三)例程

    写一个例程,使用Levels类,实现色阶调整。

    程序中定义了两个窗口,一个是图片窗口,一个是色阶定义窗口。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include "opencv2/core.hpp"
      4 #include "opencv2/imgproc.hpp"
      5 #include "opencv2/highgui.hpp"
      6  
      7 #include "Levels.hpp"
      8  
      9 using namespace std;
     10 using namespace cv;
     11  
     12 static string window_name = "Photo";
     13 static Mat src;
     14  
     15 static Mat levels_mat;
     16 static string levels_window = "Adjust Levels";
     17 static int channel = 0;
     18 Levels  levels;
     19  
     20 int   Shadow;
     21 int   Midtones = 100;
     22 int   Highlight;
     23 int   OutputShadow;
     24 int   OutputHighlight;
     25  
     26 static void invalidate()
     27 {
     28     Mat dst;
     29     levels.adjust(src, dst);
     30     imshow(window_name, dst);
     31  
     32     imshow(levels_window, levels_mat);
     33 }
     34  
     35 static void channelRead(int which_channel)
     36 {
     37     channel = which_channel;
     38     Level * CurrentChannel = NULL;
     39     switch (channel) {
     40     case 0: CurrentChannel = &levels.RGBChannel; break;
     41     case 1: CurrentChannel = &levels.RedChannel; break;
     42     case 2: CurrentChannel = &levels.GreenChannel; break;
     43     case 3: CurrentChannel = &levels.BlueChannel; break;
     44     }
     45     if ( CurrentChannel == NULL ) return;
     46  
     47     Shadow = CurrentChannel->Shadow;
     48     Midtones = int (CurrentChannel->Midtones * 100);
     49     Highlight = CurrentChannel->Highlight;
     50     OutputShadow = CurrentChannel->OutputShadow;
     51     OutputHighlight = CurrentChannel->OutputHighlight;
     52  
     53 }
     54  
     55 static void channelWrite()
     56 {
     57     Level * CurrentChannel = NULL;
     58     switch (channel) {
     59     case 0: CurrentChannel = &levels.RGBChannel; break;
     60     case 1: CurrentChannel = &levels.RedChannel; break;
     61     case 2: CurrentChannel = &levels.GreenChannel; break;
     62     case 3: CurrentChannel = &levels.BlueChannel; break;
     63     }
     64  
     65     if ( CurrentChannel == NULL )
     66         return ;
     67  
     68     CurrentChannel->Shadow = Shadow;
     69     CurrentChannel->Midtones = Midtones / 100.0;
     70     CurrentChannel->Highlight = Highlight;
     71     CurrentChannel->OutputShadow = OutputShadow;
     72     CurrentChannel->OutputHighlight = OutputHighlight;
     73  
     74     invalidate();
     75 }
     76  
     77  
     78 static void callbackAdjust(int , void *)
     79 {
     80     channelWrite();
     81     invalidate();
     82 }
     83  
     84  
     85 static void callbackAdjustChannel(int , void *)
     86 {
     87     channelRead(channel);
     88     setTrackbarPos("Shadow", levels_window, Shadow);
     89     setTrackbarPos("Midtones", levels_window, Midtones);
     90     setTrackbarPos("Highlight", levels_window, Highlight);
     91     setTrackbarPos("OutShadow", levels_window, OutputShadow);
     92     setTrackbarPos("OutHighlight", levels_window, OutputHighlight);
     93     invalidate();
     94 }
     95  
     96  
     97 int main()
     98 {
     99     //read image file
    100     src = imread("building.jpg");
    101     if ( !src.data ) {
    102         cout << "error read image" << endl;
    103         return -1;
    104     }
    105  
    106     //create window
    107     namedWindow(window_name);
    108     imshow(window_name, src);
    109  
    110  
    111     //create window for levels
    112     namedWindow(levels_window);
    113     levels_mat = Mat::ones(100,400, CV_8UC3);
    114     levels_mat.setTo( Scalar(255,255,255) );
    115     imshow(levels_window, levels_mat);
    116  
    117     channelRead(0);
    118     createTrackbar("Channel", levels_window, &channel,  3, callbackAdjustChannel);
    119     createTrackbar("Shadow", levels_window, &Shadow,  255, callbackAdjust);
    120     createTrackbar("Midtones", levels_window, &Midtones,  200, callbackAdjust);
    121     createTrackbar("Highlight", levels_window, &Highlight,  255, callbackAdjust);
    122     createTrackbar("OutShadow", levels_window, &OutputShadow,  255, callbackAdjust);
    123     createTrackbar("OutHighlight", levels_window, &OutputHighlight,  255, callbackAdjust);
    124  
    125     waitKey();
    126  
    127     return 0;
    128  
    129 }

    运行效果:

    原图:

    先对红色通道(Channel = 1)调整各项色阶定义值,进行单通道色阶调整,效果如下:

    再对RGB通道(Channel = 0)进行整体色阶调整,效果如下:

  • 相关阅读:
    转载(SQL Server 存储过程的分页)
    学会了怎么样利用捕获异常提示数据库主键重复错误
    遇到.net加了验证控件的表单无法提交的问题
    过劳死IT界杀手 [注:该文属于转载,非原创],好可怕啊!
    很喜欢的一些道理。
    学会了在DropDownList的项里加多个空格
    好东东:asp.net利用多线程执行长时间的任务,客户端显示出任务的执行进度的示例
    javascript判断字符长度最好的方法
    layui中使用layverify进行非必填整数校验
    SuppressWarnings抑制警告的关键字
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/13801333.html
Copyright © 2020-2023  润新知