• OpenCV实现Photoshop算法(八): 可选颜色


    可选颜色(Selective Color)

    可选颜色是Photoshop的常用图像调整功能。 可以选定某些颜色进行调整,而不影响其它颜色。

    可选颜色功能常用于创造某种色调。

    首先选取颜色,有9种: 红、黄、绿、青、蓝、洋红、白、中性色、黑

    然后,可以调整该颜色的 :  青、洋红、黄、黑 组成要素。

    调整方法可以选择 相对 或 绝对 两种。

    (一)可选颜色的原理

    要了解相关原理

    (二)OpenCV实现

    1,我用OpenCV 编写了一个 SelectiveColor 类,实现可选颜色调整。在源文件 SelectiveColor.hpp,  SelectiveColor.cpp中

    3, 使用方法: SelectiveColor类有一个属性colors[9], 定义了9个颜色通道(红、黄、绿、青、蓝、洋红、白、中性色、黑)。

    每个颜色通道有cyan, magenta, yellow, black 四个值。设置好所需通道和值,再调用SelectiveColor类的adjust()方法即可对图像进行  可选颜色调整。

    (三)例程

    使用SelectiveColor类,进行可选颜色调整。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include "opencv2/core.hpp"
      4 #include "opencv2/imgproc.hpp"
      5 #include "opencv2/highgui.hpp"
      6  
      7 #include "SelectiveColor.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 adjust_mat;
     16 static string adjust_window = "Selective Color";
     17 static int color = 2;
     18 SelectiveColor  selectiveColor;
     19  
     20 vector<Point> points;
     21  
     22 int   cyan;
     23 int   magenta;
     24 int   yellow;
     25 int   black;
     26 int   is_absolute;
     27  
     28 static void invalidate()
     29 {
     30     Mat dst;
     31     selectiveColor.adjust(src, dst);
     32  
     33     imshow(window_name, dst);
     34     imshow(adjust_window, adjust_mat);
     35 }
     36  
     37 static void channelRead(int which)
     38 {
     39     color = which;
     40  
     41     SelectiveColorAdjust * current = NULL;
     42     if ( color >=0 && color <= 9)
     43         current = &(selectiveColor.colors[color]);
     44     if ( current == NULL ) return;
     45  
     46     cyan = (current->cyan < 0) ? (current->cyan + 1) * 100 : current->cyan * 100;
     47     magenta = (current->magenta < 0) ? (current->magenta + 1) * 100 : current->magenta * 100;
     48     yellow = (current->yellow < 0) ? (current->yellow + 1) * 100 : current->yellow * 100;
     49     black = (current->black < 0) ? (current->black + 1) * 100 : current->black * 100;
     50  
     51     if ( selectiveColor.isAbsolute )
     52         is_absolute = 1;
     53     else
     54         is_absolute = 0;
     55  
     56 }
     57  
     58 static void channelWrite()
     59 {
     60     SelectiveColorAdjust * current = NULL;
     61     if ( color >=0 && color <= 9)
     62         current = &(selectiveColor.colors[color]);
     63     if ( current == NULL ) return;
     64  
     65     current->cyan = (cyan - 100 ) / 100.0;
     66     current->magenta =  (magenta - 100 ) / 100.0;
     67     current->yellow =  (yellow - 100 ) / 100.0;
     68     current->black =  (black - 100 ) / 100.0;
     69  
     70     selectiveColor.isAbsolute = ( is_absolute == 1 );
     71     invalidate();
     72 }
     73  
     74  
     75 static void callbackAdjust(int , void *)
     76 {
     77     channelWrite();
     78     invalidate();
     79 }
     80  
     81  
     82 static void callbackAdjustChannel(int , void *)
     83 {
     84     channelRead(color);
     85     setTrackbarPos("cyan", adjust_window, cyan);
     86     setTrackbarPos("magenta", adjust_window, magenta);
     87     setTrackbarPos("yellow", adjust_window, yellow);
     88     setTrackbarPos("black", adjust_window, black);
     89     setTrackbarPos("Absolute", adjust_window, is_absolute);
     90     invalidate();
     91 }
     92  
     93 static void callbackMouseEvent(int mouseEvent, int x, int y, int flags, void* param)
     94 {
     95     switch(mouseEvent) {
     96     case CV_EVENT_LBUTTONDOWN:
     97         break;
     98     case CV_EVENT_MOUSEMOVE:
     99         break;
    100     case CV_EVENT_LBUTTONUP:
    101         points.push_back(Point(x, y));
    102         invalidate();
    103         break;
    104     case CV_EVENT_LBUTTONDBLCLK:
    105         points.clear();
    106         invalidate();
    107         break;
    108     }
    109     return;
    110 }
    111  
    112 int main()
    113 {
    114     //read image file
    115     src = imread("building.jpg");
    116     if ( !src.data ) {
    117         cout << "error read image" << endl;
    118         return -1;
    119     }
    120  
    121     //create window
    122     namedWindow(window_name);
    123     imshow(window_name, src);
    124     setMouseCallback(window_name, callbackMouseEvent, NULL );
    125  
    126  
    127     //create window for levels
    128     namedWindow(adjust_window);
    129     adjust_mat = Mat::ones(100,400, CV_8UC3);
    130     adjust_mat.setTo( Scalar(255,255,255) );
    131     imshow(adjust_window, adjust_mat);
    132  
    133     channelRead(0);
    134     createTrackbar("Color", adjust_window, &color,  8, callbackAdjustChannel);
    135     createTrackbar("cyan", adjust_window, &cyan,  200, callbackAdjust);
    136     createTrackbar("magenta", adjust_window, &magenta,  200, callbackAdjust);
    137     createTrackbar("yellow", adjust_window, &yellow,  200, callbackAdjust);
    138     createTrackbar("black", adjust_window, &black,  200, callbackAdjust);
    139     createTrackbar("Absolute", adjust_window, &is_absolute,  1, callbackAdjust);
    140  
    141     waitKey();
    142     return 0;
    143 }

    运行效果:

    原图:

    对红色 (color = 0 ), 进行调整后

  • 相关阅读:
    SVN和IntelliJ IDEA忽略node_module设置
    通过出版一本案例方面的图书来包装自己(实施篇)
    在著名出版社出版书,你也行——记录我写书出版的经历和体会
    从事务角度粗窥架构的可扩展性和可维护性:内容整理自java web轻量级开发面试教程
    Hibernate(或其它ORM)里的inverse用法详解,内容摘自Java web轻量级开发面试教程
    Java web轻量级开发面试教程的前言
    根据实践经验,讲述些学习Java web能少走的弯路,内容摘自java web轻量级开发面试教程
    面试时,当你有权提问时,别客气,这是个逆转的好机会(内容摘自Java Web轻量级开发面试教程)
    通过Struts了解MVC框架,兼说如何在面试中利用Struts证明自己
    从一个简单案例上手Spring MVC,同时分析Spring MVC面试问题
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/13801383.html
Copyright © 2020-2023  润新知