/*
* Adjust Curves
*
* Author: JoStudio
*/
#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 = new double[n];
memset(dy, 0, sizeof(double)*n);
dy[0] = -0.5;
double* ddy = new double[n];
memset(ddy, 0, sizeof(double)*n);
double h1;
double* s = new double[n];
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] = 6.0 * (y[j+1] - y[j]) / h1 - 2.0 * (2.0 * dy[j] + dy[j+1]) / s[j];
}
h1 = s[n-2] * s[n-2];
ddy[n-1] = 6.0 * (y[n-2] - y[n-1]) / h1 + 2.0 * (2.0 * dy[n-1] + dy[n-2]) / s[n-2];
double g = 0.0;
for(int i=0; i<=n-2; i++)
{
h1 = 0.5 * s[i] * (y[i] + y[i+1]);
h1 = h1 - s[i] * s[i] * s[i] * (ddy[i] + ddy[i+1]) / 24.0;
g = g + h1;
}
for(int j=0; j<=m-1; j++)
{
int i;
if( t[j] >= x[n-1] ) {
i = n - 2;
} else {
i = 0;
while(t[j] > x[i+1]) {
i = i + 1;
}
}
h1 = (x[i+1] - t[j]) / s[i];
h0 = h1 * h1;
z[j] = (3.0 * h0 - 2.0 * h0 * h1) * y[i];
z[j] = z[j] + s[i] * (h0 - h0 * h1) * dy[i];
h1 = (t[j] - x[i]) / s[i];
h0 = h1 * h1;
z[j] = z[j] + (3.0 * h0 - 2.0 * h0 * h1) * y[i+1];
z[j] = z[j] - s[i] * (h0 - h0 * h1) * dy[i+1];
}
delete [] s;
delete [] dy;
delete [] ddy;
return(g);
}
#define WITHIN(x1, delta, x2) ( (delta) > 0 ) ? ( (x1) <= (x2) ) : ( (x1) >= (x2) )
#define EXCEED(x1, delta, x2) ( (delta) > 0 ) ? ( (x1) >= (x2) ) : ( (x1) <= (x2) )
void dot_line(Mat &mat, const Point &p1, const Point &p2, const Scalar &color,
int thickness = 1, int lineType = 8, int line_step = 6, int blank_step = 6 );
void dot_line(Mat &mat, const Point &p1, const Point &p2, const Scalar &color,
int thickness, int lineType, int line_step, int blank_step )
{
if ( p1 == p2 ) return;
//validate line_step
line_step = ::abs(line_step);
if ( line_step == 0 ) line_step = 1;
//validate blank_step
blank_step = ::abs(blank_step);
if ( blank_step == 0 ) blank_step = 1;
//dot_ratio = blank_step / line_step;
double dot_ratio = blank_step * 1.0 / line_step;
//calculat step_x, step_y
double len, step_x, step_y;
len = sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) );
step_x = (p2.x - p1.x) / len * line_step;
step_y = (p2.y - p1.y) / len * line_step;
double x1, y1, x2, y2;
x1 = p1.x; y1 = p1.y; //start from Point p1
//draw line step by step, until meet Point p2
if ( ::abs(p1.x - p2.x) > ::abs(p1.y - p2.y) ) {
//step in direction of x-coordination
while ( WITHIN(x1, step_x, p2.x) ) {
if ( EXCEED(x1 + step_x * (1 + dot_ratio), step_x, p2.x )) {
x2 = p2.x;
y2 = p2.y;
} else if ( EXCEED(x1 + step_x, step_x, p2.x )) {
x2 = p2.x;
y2 = p2.y;
} else {
x2 = x1 + step_x;
y2 = y1 + step_y;
}
line(mat, Point(x1, y1), Point(x2, y2), color, thickness, lineType);
//step
x1 = x2 + step_x * dot_ratio;
y1 = y2 + step_y * dot_ratio;
}
} else {
//step in direction of y-coordination
while ( WITHIN(y1, step_y, p2.y) ) {
if ( EXCEED(y1 + step_y * (1 + dot_ratio), step_y, p2.y )) {
x2 = p2.x;
y2 = p2.y;
} else if ( EXCEED(y1 + step_y, step_y, p2.y )) {
x2 = p2.x;
y2 = p2.y;
} else {
x2 = x1 + step_x;
y2 = y1 + step_y;
}
line(mat, Point(x1, y1), Point(x2, y2), color, thickness, lineType);
//step
x1 = x2 + step_x * dot_ratio;
y1 = y2 + step_y * dot_ratio;
}
}
}
Curve::Curve()
{
color = Scalar(0,0,0);
back_color = Scalar(255,255,255);
tolerance = 3;
is_mouse_down = false;
points.push_back( Point(0, 0) );
points.push_back( Point(255, 255) );
current = points.end();
}
Curve::~Curve()
{
}
vector<Point>::iterator Curve::find(int x)
{
vector<Point>::iterator iter;
for (iter = points.begin(); iter != points.end(); ++iter ) {
if ( ::abs(iter->x - x ) <= tolerance )
return iter;
}
return points.end();
}
vector<Point>::iterator Curve::find(int x, int y)
{
vector<Point>::iterator iter;
for (iter = points.begin(); iter != points.end(); ++iter ) {
if ( ::abs(iter->x - x ) <= tolerance && ::abs(iter->y - y ) <= tolerance )
return iter;
}
return points.end();
}
vector<Point>::iterator Curve::add(int x, int y)
{
vector<Point>::iterator it = find(x);
if ( it == points.end() ) {
Point p(x, y);
vector<Point>::iterator iter;
for (iter = points.begin(); iter != points.end(); ++iter ) {
if ( iter == points.begin() && iter->x > p.x) {
DEBUG_PRINT("points insert at beginning");
return points.insert( iter, p );
}
if ( iter->x < x && (iter + 1) != points.end() && (iter + 1)->x > p.x) {
DEBUG_PRINT("points insert");
return points.insert( iter + 1, p );
}
}
DEBUG_PRINT("points append");
return points.insert( points.end(), p );
} else {
return it;
}
}
int Curve::calcCurve(double *output_y)
{
//if count of control points is less than 2, return linear output
if ( points.size() < 2) {
for (int i = 0; i < 256; ++i )
output_y[i] = 255 - i;
return 0;
}
//if count of control points is 2, return linear output
if ( points.size() == 2 ) {
vector<Point>::iterator point1 = points.begin();
vector<Point>::iterator point2 = point1 + 1;
double delta_y = 0;
if ( point2->x != point1->x )
delta_y = (point2->y - point1->y) * 1.0 / (point2->x - point1->x);
//create output
for ( int i = 0; i < 256; ++i ) {
if ( i < point1->x ) {
output_y[i] = point1->y;
} else if ( i >= point1->x && i < point2->x ) {
output_y[i] = COLOR_RANGE( point1->y + delta_y * (i - point1->x) );
} else {
output_y[i] = point2->y;
}
}
return 0;
}
//the count of control points is greater than 2, create spline line
int n = points.size(); //count of points
//create array of x-coordinate and y-coordinate of control points
double x[ n ];
double y[ n ];
vector<Point>::iterator start_point = points.end();
vector<Point>::iterator end_point = points.end();
vector<Point>::iterator iter;
int k = 0;
for (iter =
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
用OpenCV实现Photoshop曲线算法C++源码.zip (4个子文件)
用OpenCV实现Photoshop曲线算法C++源码
Curves.cpp 15KB
Curves.hpp 2KB
building.jpg 122KB
demo.cpp 3KB
共 4 条
- 1
资源评论
- CyberNinja2023-07-26非常感谢作者分享这个文件,它对我学习图像处理有很大的帮助。
- 贼仙呐2023-07-26通过这个文件,我学到了如何运用OpenCV对图像进行曲线调整,真是大开眼界。
- 杜拉拉到杜拉拉2023-07-26该文件提供了一个实际的示例,使我在OpenCV的学习过程中能够更好地理解曲线算法的实现原理。
- ShepherdYoung2023-07-26这个文件提供了实现Photoshop曲线算法的源码,对学习OpenCV的人来说非常有帮助。
- 乖巧是我姓名2023-07-26该文件讲解了如何利用OpenCV实现曲线算法,步骤清晰易懂,让人能够快速上手。
ok690
- 粉丝: 35
- 资源: 561
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功