仿Photoshop利用曲线对图像调整亮度与色彩

曲线调整是Photoshop的最常用的重要功能之一。对于一个RGB图像,  可以对R,  G,  B 通道进行独立的曲线调整,即,对三个通道分别使用三条曲线(Curve)。还可以再增加一条曲线对 三个通道进行整体调整。 因此,对一个图像,可以用四条曲线调整。最终的结果,是四条曲线调整后合并产生的结果。

图中,横轴是输入,比左到右分别表示0到255.  纵轴是输出,从下到上分别表示0到255.

具体代码分三个实现:

头文件 Curves.h

/*
 * Adjust Curves
 */

#ifndef OPENCV2_PS_CURVES_HPP_
#define OPENCV2_PS_CURVES_HPP_
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;

namespace cv {

	/**
	 * Class of Curve for one channel
	 */
	class Curve {
	protected:
		Scalar color;
		Scalar back_color;
		int tolerance; //
		bool is_mouse_down;
		vector<Point> points;  //control points 
		vector<Point>::iterator current;  //pointer to current point

		vector<Point>::iterator  find(int x);
		vector<Point>::iterator  find(int x, int y);
		vector<Point>::iterator  add(int x, int y);

	public:
		Curve();
		virtual ~Curve();

		int calcCurve(double* z); //

		void draw(Mat& mat);  //
		void mouseDown(int x, int y); 
		bool mouseMove(int x, int y); 
		void mouseUp(int x, int y); 

		void clearPoints(); 
		int  addPoint(const Point& p); 
		int  deletePoint(const Point& p); 
		int  movePoint(const Point& p, int x, int y); 
	};

	/**
	 * Class of Curves for all channels
	 */
	class Curves {
	protected:
		void createColorTables(uchar colorTables[][256]);
	public:
		Curves();
		virtual ~Curves();

		Curve RGBChannel;   //RGB
		Curve RedChannel;   //Red
		Curve GreenChannel; //Green
		Curve BlueChannel;  //Blue

		Curve* CurrentChannel; 

		void draw(Mat& mat); 
		void mouseDown(int x, int y); 
		bool mouseMove(int x, int y);
		void mouseUp(int x, int y); 

	
		int adjust(InputArray src, OutputArray dst, InputArray mask = noArray());

	};
#endif/* OPENCV2_PS_CURVES_HPP_ */

	
	void dot_line(Mat& mat, Point& p1, Point& p2, Scalar& color, int step = 8);

} /* namespace cv */

Curves.cpp

/*
 * Adjust Curves
 *
 */

#include "Curves.hpp"

#ifdef HAVE_OPENMP
#include <omp.h>
#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)

#include <iostream>
#define DEBUG_PRINT(a)  cout << (a) << endl
#define PRINT_VAR(var)  cout << #var << " = " << (var) <<  endl

namespace cv {

	/**
	 * spline function
	 *
	 * @param x [in]  array of x-coordinate of control points
	 * @param y [in]  array of y-coordinate of control points
	 * @param n [in]  count of control points
	 * @param t [in]  array of x-coordinate of output points
	 * @param m [in]  count of output points
	 * @param z [out]  array of y-coordinate of output points
	 */
	static double spline(double* x, double* y, int n, double* t, int m, double* z)
	{
		double* dy = (double*)malloc(n * sizeof(int));
		memset(dy, 0, sizeof(double) * n);
		dy[0] = -0.5;

		//double* ddy = new double[n];
		double* ddy = (double*)malloc(n * sizeof(int));
		memset(ddy, 0, sizeof(double) * n);

		double h1;
		double* s = (double*)malloc(n * sizeof(int));
		double h0 = x[1] - x[0];

		s[0] = 3.0 * (y[1] - y[0]) / (2.0 * h0) - ddy[0] * h0 / 4.0;
		for (int j = 1; j <= n - 2; ++j)
		{
			h1 = x[j + 1] - x[j];
			double alpha = h0 / (h0 + h1);
			double beta = (1.0 - alpha) * (y[j] - y[j - 1]) / h0;
			beta = 3.0 * (beta + alpha * (y[j + 1] - y[j]) / h1);
			dy[j] = -alpha / (2.0 + (1.0 - alpha) * dy[j - 1]);
			s[j] = (beta - (1.0 - alpha) * s[j - 1]);
			s[j] = s[j] / (2.0 + (1.0 - alpha) * dy[j - 1]);
			h0 = h1;
		}
		dy[n - 1] = (3.0 * (y[n - 1] - y[n - 2]) / h1 + ddy[n - 1] * h1 / 2.0 - s[n - 2]) / (2.0 + dy[n - 2]);

		for (int j = n - 2; j >= 0; --j)
		{
			dy[j] = dy[j] * dy[j + 1] + s[j];
		}

		for (int j = 0; j <= n - 2; ++j)
		{
			s[j] = x[j + 1] - x[j];
		}

		for (int j = 0; j <= n - 2; ++j)
		{
			h1 = s[j] * s[j];
			ddy[j
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序小K

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值