[C++][opencv]基于opencv实现photoshop算法色阶调整

【测试环境】

vs2019

opencv==4.8.0

【效果演示】

【核心实现代码】

Levels.hpp

#ifndef OPENCV2_PS_LEVELS_HPP_
#define OPENCV2_PS_LEVELS_HPP_

#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

namespace cv {

/**
 * Class of Level for one channel
 */
class Level {
public:
	int   Shadow;  //输入色阶黑点值
	float Midtones; //输入色阶灰点值(注意是浮点数)
	int   Highlight; //输入色阶白点值

	int   OutputShadow; //输出色阶黑点值
	int   OutputHighlight; //输出色阶白点值

	Level();
	virtual ~Level();

	bool createColorTable(uchar * colorTable);
	void clear();
};

/**
 * Class of Levels for all channels
 */
class Levels {
protected:
	bool createColorTables(uchar colorTables[][256]);

public:
	Level RGBChannel;  //RGB整体调整
	Level RedChannel;  //红色通道
	Level GreenChannel; //绿色通道
	Level BlueChannel; //蓝色通道

	Levels();
	virtual ~Levels();

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


} /* namespace cv */

#endif /* OPENCV2_PS_LEVELS_HPP_ */

Levels.cpp

#include "Levels.hpp"

namespace cv {

Level::Level() {
	clear();
}

Level::~Level() {

}

void Level::clear() {
	Shadow = OutputShadow = 0;
	Highlight = OutputHighlight = 255;
	Midtones = 1.0;
}

//create color table for a channel
bool Level::createColorTable(uchar * colorTable)
{
    int diff = (int)(Highlight - Shadow);
    int outDiff = (int)(OutputHighlight - OutputShadow);

    if (!((Highlight <= 255 && diff <= 255 && diff >= 2) ||
        (OutputShadow <= 255 && OutputHighlight <= 255 && outDiff < 255) ||
        (!(Midtones > 9.99 && Midtones > 0.1) && Midtones != 1.0)))
        return false;

    double coef = 255.0 / diff;
    double outCoef = outDiff / 255.0;
    double exponent = 1.0 / Midtones;

    for (int i = 0; i < 256; i ++)
    {
        int v;
        // calculate black field and white field of input level
        if ( colorTable[i] <= (uchar)Shadow ) {
            v = 0;
        } else {
            v = (int)((colorTable[i] - Shadow) * coef + 0.5);
            if (v > 255) v = 255;
        }
        // calculate midtone field of input level
        v = (int)( pow(v / 255.0, exponent) * 255.0 + 0.5 );
        // calculate output level
        colorTable[i] = (uchar)( v * outCoef + OutputShadow + 0.5 );
    }

    return true;
}

//==================================================================
// Levels

Levels::Levels() {
}

Levels::~Levels() {

}

bool Levels::createColorTables(uchar colorTables[][256])
{
    bool result = false;
    int i, j;

    //initialize color table
    for (i = 0; i < 3; i ++) {
        for (j = 0; j < 256; j ++)
            colorTables[i][j] = (uchar)j;
    }

    //create color table for each channel
    result = BlueChannel.createColorTable( colorTables[0]);
    result = GreenChannel.createColorTable( colorTables[1]);
    result = RedChannel.createColorTable( colorTables[2]);

    result = RGBChannel.createColorTable( colorTables[0]);
    result = RGBChannel.createColorTable( colorTables[1]);
    result = RGBChannel.createColorTable( colorTables[2]);

    return result;
}


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

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

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

	uchar colorTables[3][256];

	//create color tables
	if ( ! createColorTables( colorTables ) )  {
		//error create color table"
		return 1;
	}

	//adjust each pixel
	#ifdef HAVE_OPENMP
	#pragma omp parallel for
	#endif
	for (int y = 0; y < height; y ++) {
		in = input.ptr<uchar>(y);
		out = output.ptr<uchar>(y);
		for (int x = 0; x < width; x ++) {
			for (int c = 0; c < 3; c++) {
				*out++ = colorTables[c][*in++];
			}
			for (int c = 0; c < channels - 3; c++) {
				*out++ = *in++;
			}
		}
	}

	return 0;
}


} /* namespace cv */

【完整演示代码下载】

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

相关推荐
我曾经是个程序员9 分钟前
C#Directory类文件夹基本操作大全
服务器·开发语言·c#
白云~️11 分钟前
uniappX 移动端单行/多行文字隐藏显示省略号
开发语言·前端·javascript
编码浪子16 分钟前
构建一个rust生产应用读书笔记7-确认邮件2
开发语言·后端·rust
天之涯上上32 分钟前
JAVA开发 在 Spring Boot 中集成 Swagger
java·开发语言·spring boot
2402_8575834933 分钟前
“协同过滤技术实战”:网上书城系统的设计与实现
java·开发语言·vue.js·科技·mfc
18号房客35 分钟前
计算机视觉-人工智能(AI)入门教程一
人工智能·深度学习·opencv·机器学习·计算机视觉·数据挖掘·语音识别
爱学习的白杨树39 分钟前
MyBatis的一级、二级缓存
java·开发语言·spring
OTWOL1 小时前
两道数组有关的OJ练习题
c语言·开发语言·数据结构·c++·算法
问道飞鱼1 小时前
【前端知识】强大的js动画组件anime.js
开发语言·前端·javascript·anime.js
拓端研究室1 小时前
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
android·开发语言·kotlin