当前位置: 首页 > news >正文

[C++][opencv]基于opencv实现photoshop算法可选颜色调整

【测试环境】

vs2019

opencv==4.8.0

【效果演示】

【核心实现代码】

SelectiveColor.hpp

#ifndef OPENCV2_PS_SELECTIVECOLOR_HPP_
#define OPENCV2_PS_SELECTIVECOLOR_HPP_#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;namespace cv {typedef enum select_color {SELECT_RED,SELECT_YELLOW,SELECT_GREEN,SELECT_CYAN,SELECT_BLUE,SELECT_MAGENTA,SELECT_WHITE,SELECT_MIDDLE,SELECT_BLACK
}  select_color_t;/*** Class of Adjustment for One Select Color*/
class SelectiveColorAdjust{
public:float cyan;       //青色调整值,取值范围: [-1, 1]float magenta;    //取值范围: [-1, 1]float yellow;     //取值范围: [-1, 1]float black;      //取值范围: [-1, 1]bool  defined;SelectiveColorAdjust();virtual ~SelectiveColorAdjust();void   calcDefined();
};/*** Class of Selective Color*/
class SelectiveColor {
public:bool isAbsolute;  //是否采用绝对方法SelectiveColorAdjust colors[ SELECT_BLACK + 1 ]; //9种可选颜色通道SelectiveColor();virtual ~SelectiveColor();int adjust(InputArray src, OutputArray dst); //实施可选颜色调整
};} /* namespace cv */#endif /* OPENCV2_PS_SELECTIVECOLOR_HPP_ */

 SelectiveColor.cpp


#include "SelectiveColor.hpp"#define DEBUG#ifndef DEBUG#define DEBUG_PRINT(a)
#define PRINT_VAR(var)
#define PRINT_VAR1(var)
#define PRINT_VARF(var)#else#include <iostream>
using namespace std;
#define DEBUG_PRINT(a)  cout << (a) << endl
#define PRINT_VAR(var)  cout << #var << " = " << (var) <<  endl
#define PRINT_VAR1(var) if ( nn == 0 ) cout << #var << " = " << int(var) <<  endl
#define PRINT_VARF(var) if ( nn == 0 ) cout << #var << " = " << double(var) <<  endl#endif#define SWAP(a, b, t)  do { t = a; a = b; b = t; } while(0)
#define CLIP_RANGE(value, min, max)  ( (value) > (max) ? (max) : (((value) < (min)) ? (min) : (value)) )
#define COLOR_RANGE(value)  CLIP_RANGE(value, 0, 255)#define MAX2(a, b) ( (a) > (b) ) ?  (a) : (b)
#define MAX3(a,b,c) ( ( a > b ) ?  MAX2(a,c) : MAX2(b,c) )
#define BLUE  0
#define GREEN 1
#define RED   2namespace cv {SelectiveColorAdjust:: SelectiveColorAdjust()
{cyan = 1.0;magenta = 1.0;yellow = 1.0;black = 1.0;defined = false;
}SelectiveColorAdjust::~SelectiveColorAdjust()
{}void SelectiveColorAdjust::calcDefined()
{if (cyan != 1.0 || magenta != 1.0 || yellow != 1.0 || black != 1.0 ) {defined =  true;return;}defined = false;
}//=========================================================
// SelectiveColorSelectiveColor::SelectiveColor() {isAbsolute = false;
}SelectiveColor::~SelectiveColor() {
}int SelectiveColor::adjust(InputArray src, OutputArray dst)
{Mat input = src.getMat();if( input.empty() ) {return -1;}dst.create(src.size(), src.type());Mat output = dst.getMat();//calculate color adjustment is definedfor(int i = 0; i < 9; i++ ) {colors[i].calcDefined();}const uchar *in;uchar *out;int width = input.cols;int height = input.rows;int channels = input.channels();int nn = 0;uchar t;  //tempuchar sorted[3];      //RGB value sorteduchar c[SELECT_BLACK + 1];float delta[3];  //delta of RGB valuefloat ratio[3],  ratio_positive[3], ratio_negative[3];for (int h = 0; h < height; h ++, nn++) {in = input.ptr<uchar>(h);  //pointer to input image dataout = output.ptr<uchar>(h); //pointer to output image datafor (int w = 0; w < width; w ++) {//Sort RGB values:  sorted[0] is biggest, sorted[1] is middle, sorted[2] is smallestmemcpy(sorted, in, 3);if (sorted[1] > sorted[0]) SWAP(sorted[0], sorted[1], t);if (sorted[2] > sorted[1]) SWAP(sorted[1], sorted[2], t);if (sorted[1] > sorted[0]) SWAP(sorted[0], sorted[1], t);//calculation c[] arraymemset(c, sizeof(c), 0);c[SELECT_BLUE] = in[BLUE];c[SELECT_GREEN] = in[GREEN];c[SELECT_RED] = in[RED];//subtract the smallest value from the RGBc[SELECT_BLUE]  -= sorted[2];c[SELECT_GREEN] -= sorted[2];c[SELECT_RED]   -= sorted[2];//calculate WHIT, MIDDLE, BLACKif ( sorted[2] <= 127 ) {c[SELECT_WHITE] = 0;c[SELECT_MIDDLE] = sorted[2] * 2;c[SELECT_BLACK]  = 255 - sorted[2] * 2;} else  {c[SELECT_WHITE]  = sorted[2] * 2 - 255;c[SELECT_MIDDLE] = 255 - (  sorted[2] - 127.5 ) * 2;c[SELECT_BLACK] = 0;}//calculate YELLOWif ( c[SELECT_RED] > 0 && c[SELECT_GREEN] > 0 ) {c[SELECT_YELLOW] = ( c[SELECT_RED] > c[SELECT_GREEN] ) ?  c[SELECT_GREEN] : c[SELECT_RED];c[SELECT_GREEN] -= c[SELECT_YELLOW];c[SELECT_RED]   -= c[SELECT_YELLOW];};//calculate CYANif ( c[SELECT_BLUE] > 0 && c[SELECT_GREEN] > 0 ) {c[SELECT_CYAN] = ( c[SELECT_BLUE] > c[SELECT_GREEN] ) ?  c[SELECT_GREEN] : c[SELECT_BLUE];c[SELECT_GREEN] -= c[SELECT_CYAN];c[SELECT_BLUE]  -= c[SELECT_CYAN];};//calculate MAGENTAif ( c[SELECT_BLUE] > 0 && c[SELECT_RED] > 0 ) {c[SELECT_MAGENTA] = ( c[SELECT_BLUE] > c[SELECT_RED] ) ?  c[SELECT_RED] : c[SELECT_BLUE];c[SELECT_RED]   -= c[SELECT_MAGENTA];c[SELECT_BLUE]  -= c[SELECT_MAGENTA];};//initialize delta[]delta[BLUE] = delta[GREEN] = delta[RED] = 0;//initialize ratiosfor(int i = 0; i < 3 ; i++ ) {ratio_positive[i] = in[i] / 255.0;ratio_negative[i] = ratio_positive[i] - 1 ;}//calculate each selective colorfor (int j = 0; j <= SELECT_BLACK; j++ ) {if ( colors[j].defined && (c[j] > 0) ) {if ( isAbsolute ) {ratio[RED] = colors[j].cyan + colors[j].black;ratio[RED] = CLIP_RANGE(ratio[RED], ratio_negative[RED], ratio_positive[RED]);ratio[GREEN] = colors[j].magenta + colors[j].black;ratio[GREEN] = CLIP_RANGE(ratio[GREEN], ratio_negative[GREEN], ratio_positive[GREEN]);ratio[BLUE] = colors[j].yellow + colors[j].black;ratio[BLUE] = CLIP_RANGE(ratio[BLUE], ratio_negative[BLUE], ratio_positive[BLUE]);} else {ratio[RED] = colors[j].cyan + ::abs(colors[j].cyan + 1) * colors[j].black;ratio[RED] = CLIP_RANGE(ratio[RED], -1, 1);ratio[RED] = ( ratio[RED] > 0 ) ? ratio[RED] * ratio_positive[RED] : - ratio[RED] * ratio_negative[RED];ratio[GREEN] = colors[j].magenta + ::abs(colors[j].magenta + 1) * colors[j].black;ratio[GREEN] = CLIP_RANGE(ratio[GREEN], -1, 1);ratio[GREEN] = ( ratio[GREEN] > 0 ) ? ratio[GREEN] * ratio_positive[GREEN] : - ratio[GREEN] * ratio_negative[GREEN];ratio[BLUE] = colors[j].yellow + ::abs(colors[j].yellow + 1) * colors[j].black;ratio[BLUE] = CLIP_RANGE(ratio[BLUE], -1, 1);ratio[BLUE] = ( ratio[BLUE] > 0 ) ? ratio[BLUE] * ratio_positive[BLUE] : - ratio[BLUE] * ratio_negative[BLUE];}delta[RED] -=  c[j] * ratio[RED];delta[GREEN] -=  c[j] * ratio[GREEN];delta[BLUE] -=  c[j] * ratio[BLUE];}}//save to outputout[BLUE]  = COLOR_RANGE( in[BLUE] + delta[BLUE] );out[GREEN] = COLOR_RANGE( in[GREEN] + delta[GREEN] );out[RED]   = COLOR_RANGE( in[RED] + delta[RED] );//move pointer forwardin += 3;out += 3;for (int j = 0; j < channels - 3; j++) {*out++ = *in++;}}}return 0;
}} /* namespace cv */

【完整演示代码下载地址】

https://download.csdn.net/download/FL1623863129/88600788

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 微前端架构下的应用版本回退策略与实践
  • C语言 | Leetcode C语言题解之第341题扁平化嵌套列表迭代器
  • idea付费插件,哪个比较好用?
  • 书生浦语大模型全链路开源开放体系学习
  • Docker和虚拟机的区别详细讲解
  • Android T about screen rotation(二)
  • spring boot 接收第三方mq消息
  • 基于JAVA美容院管理系统(源码+论文+讲解等)
  • Windows利用ssh免密码登录Linux
  • 应急响应-DDOS-典型案例
  • Jmeter接口测试断言详解
  • Windows 系统下 MongoDB和PostgreSQL数据库数据的备份和恢复
  • 使用Redis记录错误次数、序列号锁定和冻结时间的实现步骤示例[超详细]
  • WUP-MY-LABEL-PRINTER 旻佑热敏打印机标签打印uniapp插件使用说明
  • 革新测试管理:集远程、协同、自动化于一身的统一测试管理平台
  • 收藏网友的 源程序下载网
  • (三)从jvm层面了解线程的启动和停止
  • 230. Kth Smallest Element in a BST
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • magento2项目上线注意事项
  • Mysql5.6主从复制
  • October CMS - 快速入门 9 Images And Galleries
  • python 装饰器(一)
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 分享几个不错的工具
  • 关于List、List?、ListObject的区别
  • 关于字符编码你应该知道的事情
  • 利用jquery编写加法运算验证码
  • 实战|智能家居行业移动应用性能分析
  • 微信小程序:实现悬浮返回和分享按钮
  • 想写好前端,先练好内功
  • 小程序01:wepy框架整合iview webapp UI
  • 用Canvas画一棵二叉树
  • 阿里云移动端播放器高级功能介绍
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • !$boo在php中什么意思,php前戏
  • # 飞书APP集成平台-数字化落地
  • (2.2w字)前端单元测试之Jest详解篇
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (6)STL算法之转换
  • (STM32笔记)九、RCC时钟树与时钟 第一部分
  • (笔试题)分解质因式
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (排序详解之 堆排序)
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转) Face-Resources
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转)创业家杂志:UCWEB天使第一步
  • (转)详解PHP处理密码的几种方式
  • ***原理与防范
  • .NET Framework .NET Core与 .NET 的区别
  • .net 简单实现MD5
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比