[C++][opencv]基于opencv实现photoshop算法灰度化图像

测试环境】

vs2019

opencv==4.8.0

【效果演示】

【核心实现代码】

BlackWhite.hpp

复制代码
#ifndef OPENCV2_PS_BLACKWHITE_HPP_
#define OPENCV2_PS_BLACKWHITE_HPP_

#include "opencv2/core.hpp"

namespace cv {

class BlackWhite {
public:
	float 	red;     //红色的灰度系数值,取值范围: [-1.0, 1.0]
	float 	yellow;  //黄色的灰度系数值,取值范围: [-1.0, 1.0]
	float 	green;   //绿色的灰度系数值,取值范围: [-1.0, 1.0]
	float 	cyan;    //青色的灰度系数值,取值范围: [-1.0, 1.0]
	float 	blue;    //蓝色的灰度系数值,取值范围: [-1.0, 1.0]
	float 	magenta; //洋红色的灰度系数值,取值范围: [-1.0, 1.0]

	BlackWhite();
	virtual ~BlackWhite();

	int adjust(InputArray src, OutputArray dst);//实施黑白调整
};

} /* namespace cv */

#endif /* OPENCV2_PS_BLACKWHITE_HPP_ */

BlackWhite.cpp

复制代码
#include "BlackWhite.hpp"

#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)

//color index
typedef enum COLOR_INDEX {
	INDEX_RED,
	INDEX_YELLOW,
	INDEX_GREEN,
	INDEX_CYAN,
	INDEX_BLUE,
	INDEX_MAGENTA
} color_index_t;

namespace cv {

BlackWhite::BlackWhite()
{
	//set to default settings
	red = 0.4;
	yellow = 0.6;
	green = 0.4;
	cyan = 0.6;
	blue = 0.2;
	magenta = 0.8;
}

BlackWhite::~BlackWhite() {
}


int BlackWhite::adjust(InputArray src, OutputArray dst)
{
	Mat input = src.getMat();
	if( input.empty() ) {
		return -1;
	}

	dst.create(src.size(), src.type());
	Mat output = dst.getMat();

	int blackWhiteParams[6];
	blackWhiteParams[0] = CLIP_RANGE(red     * 100, -100, 100);
	blackWhiteParams[1] = CLIP_RANGE(yellow  * 100, -100, 100);
	blackWhiteParams[2] = CLIP_RANGE(green   * 100, -100, 100);
	blackWhiteParams[3] = CLIP_RANGE(cyan    * 100, -100, 100);
	blackWhiteParams[4] = CLIP_RANGE(blue    * 100, -100, 100);
	blackWhiteParams[5] = CLIP_RANGE(magenta * 100, -100, 100);

	const uchar *in;
	uchar *out;
	int channels  = input.channels();
	int rows = input.rows;
	int cols = input.cols;
	uchar gray;

	int tmp;
	int values[3];
	int indexes[3];
	int ratio_max;
	int ratio_max_mid;

	for (int y = 0; y < rows; y ++ )
	{
		in = input.ptr<uchar>(y);
		out = output.ptr<uchar>(y);
		for (int x = 0; x < cols; x ++)
		{
			//read RGB into values, set index in indexes.
			values[0] = in[0]; values[1] = in[1]; values[2] = in[2];
			indexes[0]=INDEX_BLUE; indexes[1]=INDEX_GREEN; indexes[2]=INDEX_RED;

			//sort values and indexes
			if ( values[1] > values[0] ) {
				SWAP(values[0], values[1], tmp);
				SWAP(indexes[0], indexes[1], tmp);
			}

			if ( values[2] > values[1] ) {
				SWAP(values[1], values[2], tmp);
				SWAP(indexes[1], indexes[2], tmp);
			}

			if ( values[1] > values[0] ) {
				SWAP(values[0], values[1], tmp);
				SWAP(indexes[0], indexes[1], tmp);
			}

			//get ratio_max
			ratio_max = blackWhiteParams[ indexes[0] ];

			//calculate ratio_max_mid
			if ( indexes[0] == INDEX_RED ) {
				tmp = (indexes[1] == INDEX_GREEN) ? INDEX_YELLOW : INDEX_CYAN;
			} else  if ( indexes[0] == INDEX_GREEN ) {
				tmp = (indexes[1] == INDEX_RED) ? INDEX_YELLOW : INDEX_CYAN ;
			} else {
				tmp = (indexes[1] == INDEX_RED) ? INDEX_MAGENTA : INDEX_CYAN;
			}
			ratio_max_mid = blackWhiteParams[ tmp ];

			//calculate gray =  (max - mid) * ratio_max + (mid - min) * ratio_max_mid + min
			gray = COLOR_RANGE ( (
					(values[0] - values[1]) * ratio_max +
					(values[1] - values[2]) * ratio_max_mid + values[2] * 100
					) / 100 );

			//save to ouput
			*out++ = gray;
			*out++ = gray;
			*out++ = gray;

			//move pointer forward
			in += 3;
			for (int j = 0; j < channels - 3; j++) {
				*out++ = *in++;
			}
		}
	}

	return 0;

}

} /* namespace cv */

【完整演示代码下载】

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

相关推荐
All for pursuit.7 小时前
【二分查找-2】34.在排序数组中查找元素的第一个和最后一个位置
数据结构·c++·算法·leetcode
hasty7 小时前
限制写了却没生效:OpenTelemetry Go 的 Unicode 截断边界
开发语言·后端·golang
大侠归来8 小时前
C语言与C++在基础语法上的区别
java·c语言·c++
看看我呀看看我8 小时前
基于Qt的虚拟键盘
c++·qt·qt5·qt6.3
编码者卢布9 小时前
【App Service 】WebJobs 多实例实验:谁在运行,什么时候运行?
开发语言·python
kaixin_learn_qt_ing9 小时前
Qt抽屉窗体实现demo
开发语言·qt
quantdash_cc9 小时前
Python 获取实时行情后如何进行批量筛选?从全市场快照到策略候选池
开发语言·python·数据分析·量化交易·股票数据·quantdash
cu1439 小时前
细谈GM8229的具体功能与其应用
c语言·c++·人工智能·单片机
论文复现现场9 小时前
论文复现看到“RTX 3090 or higher”:显存、CUDA、batch size 与 OOM 怎么判断?
开发语言·pytorch·batch·cuda·rtx3090
智鸟科技GemeOpen开发者智能设备9 小时前
GemeOpen 智能音箱 GSSM0B - 播放控制(Java示例)
java·开发语言·智能音箱