[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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FL1623863129

你的打赏是我写文章最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值