首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

OpenCV实现Photoshop算法-曲线调整

  • 25-02-19 03:41
  • 2765
  • 10414
blog.csdn.net

目录

效果

代码

demo.cpp

Curves.hpp

Curves.cpp

参考

下载


效果

OpenCV实现Photoshop算法-曲线调整-效果

代码

demo.cpp

/*
 * test_Curves
 */

#include
#include
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "Curves.hpp"

using namespace std;
using namespace cv;

static string window_name = "Photo";
static Mat src;

static string curves_window = "Adjust Curves";
static Mat curves_mat;
static int channel = 0;
Curves  curves;

static void invalidate()
{
    curves.draw(curves_mat);
    imshow(curves_window, curves_mat);

    Mat dst;
    curves.adjust(src, dst);
    imshow(window_name, dst);

    int y, x;
    uchar* p;

    y = 150; x = 50;
    p = dst.ptr(y) + x * 3;
    cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ")  ";

    y = 150; x = 220;
    p = dst.ptr(y) + x * 3;
    cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ")  ";

    y = 150; x = 400;
    p = dst.ptr(y) + x * 3;
    cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ")  " << endl;
}

static void callbackAdjustChannel(int, void*)
{
    switch (channel) {
    case 3:
        curves.CurrentChannel = &curves.BlueChannel;
        break;
    case 2:
        curves.CurrentChannel = &curves.GreenChannel;
        break;
    case 1:
        curves.CurrentChannel = &curves.RedChannel;
        break;
    default:
        curves.CurrentChannel = &curves.RGBChannel;
        break;
    }


    invalidate();
}

static void callbackMouseEvent(int mouseEvent, int x, int y, int flags, void* param)
{
    switch (mouseEvent) {
    case  EVENT_LBUTTONDOWN:
        curves.mouseDown(x, y);
        invalidate();
        break;
    case EVENT_MOUSEMOVE:
        if (curves.mouseMove(x, y))
            invalidate();
        break;
    case EVENT_LBUTTONUP:
        curves.mouseUp(x, y);
        invalidate();
        break;
    }
    return;
}


int main()
{
    //read image file
    src = imread("building.jpg");
    if (!src.data) {
        cout << "error read image" << endl;
        return -1;
    }

    //create window
    namedWindow(window_name);
    imshow(window_name, src);

    //create Mat for curves
    curves_mat = Mat::ones(256, 256, CV_8UC3);

    //create window for curves
    namedWindow(curves_window);
    setMouseCallback(curves_window, callbackMouseEvent, NULL);
    createTrackbar("Channel", curves_window, &channel, 3, callbackAdjustChannel);


    // 范例:用程序代码在Red通道中定义一条曲线
    //    curves.RedChannel.clearPoints();
    //    curves.RedChannel.addPoint( Point(10,  10) );
    //    curves.RedChannel.addPoint( Point(240, 240) );
    //    curves.RedChannel.addPoint( Point(127, 127) );

    invalidate();


    waitKey();

    return 0;

}
 

  1. /*
  2. * test_Curves
  3. */
  4. #include <cstdio>
  5. #include <iostream>
  6. #include "opencv2/core.hpp"
  7. #include "opencv2/imgproc.hpp"
  8. #include "opencv2/highgui.hpp"
  9. #include "Curves.hpp"
  10. using namespace std;
  11. using namespace cv;
  12. static string window_name = "Photo";
  13. static Mat src;
  14. static string curves_window = "Adjust Curves";
  15. static Mat curves_mat;
  16. static int channel = 0;
  17. Curves curves;
  18. static void invalidate()
  19. {
  20. curves.draw(curves_mat);
  21. imshow(curves_window, curves_mat);
  22. Mat dst;
  23. curves.adjust(src, dst);
  24. imshow(window_name, dst);
  25. int y, x;
  26. uchar* p;
  27. y = 150; x = 50;
  28. p = dst.ptr<uchar>(y) + x * 3;
  29. cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ") ";
  30. y = 150; x = 220;
  31. p = dst.ptr<uchar>(y) + x * 3;
  32. cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ") ";
  33. y = 150; x = 400;
  34. p = dst.ptr<uchar>(y) + x * 3;
  35. cout << "(" << int(p[2]) << ", " << int(p[1]) << ", " << int(p[0]) << ") " << endl;
  36. }
  37. static void callbackAdjustChannel(int, void*)
  38. {
  39. switch (channel) {
  40. case 3:
  41. curves.CurrentChannel = &curves.BlueChannel;
  42. break;
  43. case 2:
  44. curves.CurrentChannel = &curves.GreenChannel;
  45. break;
  46. case 1:
  47. curves.CurrentChannel = &curves.RedChannel;
  48. break;
  49. default:
  50. curves.CurrentChannel = &curves.RGBChannel;
  51. break;
  52. }
  53. invalidate();
  54. }
  55. static void callbackMouseEvent(int mouseEvent, int x, int y, int flags, void* param)
  56. {
  57. switch (mouseEvent) {
  58. case EVENT_LBUTTONDOWN:
  59. curves.mouseDown(x, y);
  60. invalidate();
  61. break;
  62. case EVENT_MOUSEMOVE:
  63. if (curves.mouseMove(x, y))
  64. invalidate();
  65. break;
  66. case EVENT_LBUTTONUP:
  67. curves.mouseUp(x, y);
  68. invalidate();
  69. break;
  70. }
  71. return;
  72. }
  73. int main()
  74. {
  75. //read image file
  76. src = imread("building.jpg");
  77. if (!src.data) {
  78. cout << "error read image" << endl;
  79. return -1;
  80. }
  81. //create window
  82. namedWindow(window_name);
  83. imshow(window_name, src);
  84. //create Mat for curves
  85. curves_mat = Mat::ones(256, 256, CV_8UC3);
  86. //create window for curves
  87. namedWindow(curves_window);
  88. setMouseCallback(curves_window, callbackMouseEvent, NULL);
  89. createTrackbar("Channel", curves_window, &channel, 3, callbackAdjustChannel);
  90. // 范例:用程序代码在Red通道中定义一条曲线
  91. // curves.RedChannel.clearPoints();
  92. // curves.RedChannel.addPoint( Point(10, 10) );
  93. // curves.RedChannel.addPoint( Point(240, 240) );
  94. // curves.RedChannel.addPoint( Point(127, 127) );
  95. invalidate();
  96. waitKey();
  97. return 0;
  98. }

Curves.hpp

  1. /*
  2. * Adjust Curves
  3. */
  4. #ifndef OPENCV2_PS_CURVES_HPP_
  5. #define OPENCV2_PS_CURVES_HPP_
  6. #include "opencv2/core.hpp"
  7. #include "opencv2/imgproc.hpp"
  8. #include "opencv2/highgui.hpp"
  9. using namespace std;
  10. using namespace cv;
  11. namespace cv {
  12. /**
  13. * Class of Curve for one channel
  14. */
  15. class Curve {
  16. protected:
  17. Scalar color;
  18. Scalar back_color;
  19. int tolerance; //鼠标按下或移动时,捕获曲线点的误差范围
  20. bool is_mouse_down;
  21. vector<Point> points; //control points 曲线的所有控制点
  22. vector<Point>::iterator current; //pointer to current point 当前控制点的指针
  23. vector<Point>::iterator find(int x);
  24. vector<Point>::iterator find(int x, int y);
  25. vector<Point>::iterator add(int x, int y);
  26. public:
  27. Curve();
  28. virtual ~Curve();
  29. int calcCurve(double *z); //供内部调用的方法:计算曲线
  30. void draw(Mat &mat); //将曲线画在mat上
  31. void mouseDown(int x, int y); //当鼠标按下,请调用mouseDown()方法
  32. bool mouseMove(int x, int y); //当鼠标移动,请调用mouseMove()方法
  33. void mouseUp(int x, int y); //当鼠标抬起,请调用mouseUp()方法
  34. //以下方法用于:用编程方式生成曲线
  35. void clearPoints(); //清除曲线上所有的点
  36. int addPoint(const Point &p); //增加一个点
  37. int deletePoint(const Point &p); //删除一个点
  38. int movePoint(const Point &p, int x, int y); //移动一个点
  39. };
  40. /**
  41. * Class of Curves for all channels
  42. */
  43. class Curves {
  44. protected:
  45. void createColorTables(uchar colorTables[][256]);
  46. public:
  47. Curves();
  48. virtual ~Curves();
  49. Curve RGBChannel; //RGB总通道
  50. Curve RedChannel; //Red通道
  51. Curve GreenChannel; //Green通道
  52. Curve BlueChannel; //Blue通道
  53. Curve * CurrentChannel; //当前通道的指针
  54. void draw(Mat &mat); //将曲线画在mat上
  55. void mouseDown(int x, int y); //当鼠标按下,请调用mouseDown()方法
  56. bool mouseMove(int x, int y); //当鼠标移动,请调用mouseMove()方法
  57. void mouseUp(int x, int y); //当鼠标抬起,请调用mouseUp()方法
  58. //实施曲线调整
  59. int adjust(InputArray src, OutputArray dst, InputArray mask = noArray());
  60. };
  61. //画一条虚线
  62. void dot_line(Mat &mat, Point &p1, Point &p2, Scalar &color, int step = 8);
  63. } /* namespace cv */
  64. #endif /* OPENCV2_PS_CURVES_HPP_ */

Curves.cpp

  1. #include "Curves.hpp"
  2. #ifdef HAVE_OPENMP
  3. #include <omp.h>
  4. #endif
  5. #define SWAP(a, b, t) do { t = a; a = b; b = t; } while(0)
  6. #define CLIP_RANGE(value, min, max) ( (value) > (max) ? (max) : (((value) < (min)) ? (min) : (value)) )
  7. #define COLOR_RANGE(value) CLIP_RANGE((value), 0, 255)
  8. #include <iostream>
  9. #define DEBUG_PRINT(a) cout << (a) << endl
  10. #define PRINT_VAR(var) cout << #var << " = " << (var) << endl
  11. namespace cv {
  12. /**
  13. * spline function
  14. *
  15. * @param x [in] array of x-coordinate of control points
  16. * @param y [in] array of y-coordinate of control points
  17. * @param n [in] count of control points
  18. * @param t [in] array of x-coordinate of output points
  19. * @param m [in] count of output points
  20. * @param z [out] array of y-coordinate of output points
  21. */
  22. static double spline(double *x, double *y, int n, double *t, int m, double *z)
  23. {
  24. double* dy = new double[n];
  25. memset(dy, 0, sizeof(double)*n);
  26. dy[0] = -0.5;
  27. double* ddy = new double[n];
  28. memset(ddy, 0, sizeof(double)*n);
  29. double h1;
  30. double* s = new double[n];
  31. double h0 = x[1] - x[0];
  32. s[0] = 3.0 * (y[1] - y[0]) / (2.0 * h0) - ddy[0] * h0 / 4.0;
  33. for( int j = 1; j <= n - 2; ++j )
  34. {
  35. h1 = x[j + 1] - x[j];
  36. double alpha = h0 / (h0 + h1);
  37. double beta = (1.0 - alpha) * (y[j] - y[j - 1]) / h0;
  38. beta = 3.0 * (beta + alpha * ( y[j + 1] - y[j] ) / h1);
  39. dy[j] = -alpha / (2.0 + (1.0 - alpha) * dy[j - 1]);
  40. s[j] = (beta - (1.0 - alpha) * s[j - 1]);
  41. s[j] = s[j] / (2.0 + (1.0 - alpha) * dy[j - 1]);
  42. h0 = h1;
  43. }
  44. 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]);
  45. for( int j = n - 2; j >= 0; --j )
  46. {
  47. dy[j] = dy[j] * dy[j + 1] + s[j];
  48. }
  49. for( int j = 0; j <= n - 2; ++j )
  50. {
  51. s[j] = x[j + 1] - x[j];
  52. }
  53. for( int j = 0; j <= n - 2; ++j )
  54. {
  55. h1 = s[j] * s[j];
  56. ddy[j] = 6.0 * (y[j+1] - y[j]) / h1 - 2.0 * (2.0 * dy[j] + dy[j+1]) / s[j];
  57. }
  58. h1 = s[n-2] * s[n-2];
  59. 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];
  60. double g = 0.0;
  61. for(int i=0; i<=n-2; i++)
  62. {
  63. h1 = 0.5 * s[i] * (y[i] + y[i+1]);
  64. h1 = h1 - s[i] * s[i] * s[i] * (ddy[i] + ddy[i+1]) / 24.0;
  65. g = g + h1;
  66. }
  67. for(int j=0; j<=m-1; j++)
  68. {
  69. int i;
  70. if( t[j] >= x[n-1] ) {
  71. i = n - 2;
  72. } else {
  73. i = 0;
  74. while(t[j] > x[i+1]) {
  75. i = i + 1;
  76. }
  77. }
  78. h1 = (x[i+1] - t[j]) / s[i];
  79. h0 = h1 * h1;
  80. z[j] = (3.0 * h0 - 2.0 * h0 * h1) * y[i];
  81. z[j] = z[j] + s[i] * (h0 - h0 * h1) * dy[i];
  82. h1 = (t[j] - x[i]) / s[i];
  83. h0 = h1 * h1;
  84. z[j] = z[j] + (3.0 * h0 - 2.0 * h0 * h1) * y[i+1];
  85. z[j] = z[j] - s[i] * (h0 - h0 * h1) * dy[i+1];
  86. }
  87. delete [] s;
  88. delete [] dy;
  89. delete [] ddy;
  90. return(g);
  91. }
  92. #define WITHIN(x1, delta, x2) ( (delta) > 0 ) ? ( (x1) <= (x2) ) : ( (x1) >= (x2) )
  93. #define EXCEED(x1, delta, x2) ( (delta) > 0 ) ? ( (x1) >= (x2) ) : ( (x1) <= (x2) )
  94. void dot_line(Mat &mat, const Point &p1, const Point &p2, const Scalar &color,
  95. int thickness = 1, int lineType = 8, int line_step = 6, int blank_step = 6 );
  96. void dot_line(Mat &mat, const Point &p1, const Point &p2, const Scalar &color,
  97. int thickness, int lineType, int line_step, int blank_step )
  98. {
  99. if ( p1 == p2 ) return;
  100. //validate line_step
  101. line_step = ::abs(line_step);
  102. if ( line_step == 0 ) line_step = 1;
  103. //validate blank_step
  104. blank_step = ::abs(blank_step);
  105. if ( blank_step == 0 ) blank_step = 1;
  106. //dot_ratio = blank_step / line_step;
  107. double dot_ratio = blank_step * 1.0 / line_step;
  108. //calculat step_x, step_y
  109. double len, step_x, step_y;
  110. len = sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) );
  111. step_x = (p2.x - p1.x) / len * line_step;
  112. step_y = (p2.y - p1.y) / len * line_step;
  113. double x1, y1, x2, y2;
  114. x1 = p1.x; y1 = p1.y; //start from Point p1
  115. //draw line step by step, until meet Point p2
  116. if ( ::abs(p1.x - p2.x) > ::abs(p1.y - p2.y) ) {
  117. //step in direction of x-coordination
  118. while ( WITHIN(x1, step_x, p2.x) ) {
  119. if ( EXCEED(x1 + step_x * (1 + dot_ratio), step_x, p2.x )) {
  120. x2 = p2.x;
  121. y2 = p2.y;
  122. } else if ( EXCEED(x1 + step_x, step_x, p2.x )) {
  123. x2 = p2.x;
  124. y2 = p2.y;
  125. } else {
  126. x2 = x1 + step_x;
  127. y2 = y1 + step_y;
  128. }
  129. line(mat, Point(x1, y1), Point(x2, y2), color, thickness, lineType);
  130. //step
  131. x1 = x2 + step_x * dot_ratio;
  132. y1 = y2 + step_y * dot_ratio;
  133. }
  134. } else {
  135. //step in direction of y-coordination
  136. while ( WITHIN(y1, step_y, p2.y) ) {
  137. if ( EXCEED(y1 + step_y * (1 + dot_ratio), step_y, p2.y )) {
  138. x2 = p2.x;
  139. y2 = p2.y;
  140. } else if ( EXCEED(y1 + step_y, step_y, p2.y )) {
  141. x2 = p2.x;
  142. y2 = p2.y;
  143. } else {
  144. x2 = x1 + step_x;
  145. y2 = y1 + step_y;
  146. }
  147. line(mat, Point(x1, y1), Point(x2, y2), color, thickness, lineType);
  148. //step
  149. x1 = x2 + step_x * dot_ratio;
  150. y1 = y2 + step_y * dot_ratio;
  151. }
  152. }
  153. }
  154. Curve::Curve()
  155. {
  156. color = Scalar(0,0,0);
  157. back_color = Scalar(255,255,255);
  158. tolerance = 3;
  159. is_mouse_down = false;
  160. points.push_back( Point(0, 0) );
  161. points.push_back( Point(255, 255) );
  162. current = points.end();
  163. }
  164. Curve::~Curve()
  165. {
  166. }
  167. vector<Point>::iterator Curve::find(int x)
  168. {
  169. vector<Point>::iterator iter;
  170. for (iter = points.begin(); iter != points.end(); ++iter ) {
  171. if ( ::abs(iter->x - x ) <= tolerance )
  172. return iter;
  173. }
  174. return points.end();
  175. }
  176. vector<Point>::iterator Curve::find(int x, int y)
  177. {
  178. vector<Point>::iterator iter;
  179. for (iter = points.begin(); iter != points.end(); ++iter ) {
  180. if ( ::abs(iter->x - x ) <= tolerance && ::abs(iter->y - y ) <= tolerance )
  181. return iter;
  182. }
  183. return points.end();
  184. }
  185. vector<Point>::iterator Curve::add(int x, int y)
  186. {
  187. vector<Point>::iterator it = find(x);
  188. if ( it == points.end() ) {
  189. Point p(x, y);
  190. vector<Point>::iterator iter;
  191. for (iter = points.begin(); iter != points.end(); ++iter ) {
  192. if ( iter == points.begin() && iter->x > p.x) {
  193. DEBUG_PRINT("points insert at beginning");
  194. return points.insert( iter, p );
  195. }
  196. if ( iter->x < x && (iter + 1) != points.end() && (iter + 1)->x > p.x) {
  197. DEBUG_PRINT("points insert");
  198. return points.insert( iter + 1, p );
  199. }
  200. }
  201. DEBUG_PRINT("points append");
  202. return points.insert( points.end(), p );
  203. } else {
  204. return it;
  205. }
  206. }
  207. int Curve::calcCurve(double *output_y)
  208. {
  209. //if count of control points is less than 2, return linear output
  210. if ( points.size() < 2) {
  211. for (int i = 0; i < 256; ++i )
  212. output_y[i] = 255 - i;
  213. return 0;
  214. }
  215. //if count of control points is 2, return linear output
  216. if ( points.size() == 2 ) {
  217. vector<Point>::iterator point1 = points.begin();
  218. vector<Point>::iterator point2 = point1 + 1;
  219. double delta_y = 0;
  220. if ( point2->x != point1->x )
  221. delta_y = (point2->y - point1->y) * 1.0 / (point2->x - point1->x);
  222. //create output
  223. for ( int i = 0; i < 256; ++i ) {
  224. if ( i < point1->x ) {
  225. output_y[i] = point1->y;
  226. } else if ( i >= point1->x && i < point2->x ) {
  227. output_y[i] = COLOR_RANGE( point1->y + delta_y * (i - point1->x) );
  228. } else {
  229. output_y[i] = point2->y;
  230. }
  231. }
  232. return 0;
  233. }
  234. //the count of control points is greater than 2, create spline line
  235. int n = points.size(); //count of points
  236. //create array of x-coordinate and y-coordinate of control points
  237. //double x[ n ];
  238. //double y[ n ];
  239. double* x = new double[n];
  240. double* y = new double[n];
  241. vector<Point>::iterator start_point = points.end();
  242. vector<Point>::iterator end_point = points.end();
  243. vector<Point>::iterator iter;
  244. int k = 0;
  245. for (iter = points.begin(); iter != points.end(); ++iter, ++k ) {
  246. if ( k == 0 ) start_point = iter;
  247. x[k] = iter->x - start_point->x;
  248. y[k] = iter->y;
  249. end_point = iter;
  250. }
  251. //if start_point or end_point is invalid
  252. if (start_point == points.end() || end_point == points.end() || start_point == end_point) {
  253. for (int i = 0; i < 256; ++i )
  254. output_y[i] = 255 - i;
  255. return 1;
  256. }
  257. //create array of x-coordinate of output points
  258. int m = end_point->x - start_point->x;
  259. //double t[m]; //array of x-coordinate of output points
  260. //double z[m]; //array of y-coordinate of output points
  261. double* t = new double[m];
  262. double* z = new double[m];
  263. //initialize array of x-coordinate
  264. for ( int i = 0; i< m; ++i ) {
  265. t[i] = i;
  266. }
  267. //perform spline, output y-coordinate is stored in array z
  268. spline(x, y, n, t, m, z);
  269. //create output
  270. for ( int i = 0; i < 256; ++i ) {
  271. if ( i < start_point->x ) {
  272. output_y[i] = start_point->y;
  273. } else if ( i >= start_point->x && i < end_point->x ) {
  274. output_y[i] = CLIP_RANGE(z[i - start_point->x], 0, 255);
  275. } else {
  276. output_y[i] = end_point->y;
  277. }
  278. }
  279. delete[] t;
  280. delete[] z;
  281. delete[] x;
  282. delete[] y;
  283. return 0;
  284. }
  285. void Curve::draw(Mat &mat)
  286. {
  287. int thinkness = 1;
  288. int n = 0;
  289. Point lastPoint;
  290. //clear background
  291. mat.setTo( back_color );
  292. vector<Point>::iterator it;
  293. for (it = points.begin(); it != points.end(); ++it) {
  294. cout << "point: "<< it->x << ", " << it->y << endl;
  295. }
  296. //draw lines
  297. dot_line(mat, Point( 0, 0), Point( 255, 0), Scalar(0,0,255), 1, 8, 4, 4);
  298. dot_line(mat, Point( 0, 255), Point( 255, 255), Scalar(0,0,255), 1, 8, 4, 4);
  299. dot_line(mat, Point(63, 0), Point(63, 255), color, 1, 8, 4, 4);
  300. dot_line(mat, Point(127, 0), Point(127, 255), color, 1, 8, 4, 4);
  301. dot_line(mat, Point(191, 0), Point(191, 255), color, 1, 8, 4, 4);
  302. dot_line(mat, Point(0, 255 - 63), Point(255, 255 - 63), color, 1, 8, 4, 4);
  303. dot_line(mat, Point(0, 255 - 127), Point(255, 255 - 127), color, 1, 8, 4, 4);
  304. dot_line(mat, Point(0, 255 - 191), Point(255, 255 - 191), color, 1, 8, 4, 4);
  305. //create curve
  306. double z[256];
  307. calcCurve(z);
  308. for (int i = 1; i < 256; ++i ) {
  309. line( mat, Point(i-1, 255 - z[i-1]), Point(i, 255 - z[i]), color, 1, 8 );
  310. }
  311. //draw control points
  312. vector<Point>::iterator iter, iter_next;
  313. for (iter = points.begin(); iter != points.end(); ++iter, ++n ) {
  314. thinkness = (iter == current) ? -1 : 1;
  315. rectangle(mat, Point(iter->x - 2, 255 - iter->y + 2),
  316. Point(iter->x + 2, 255 - iter->y - 2), color, thinkness, 8);
  317. }
  318. }
  319. void Curve::mouseDown(int x, int y)
  320. {
  321. y = 255 - y;
  322. current = add( x , y );
  323. is_mouse_down = true;
  324. }
  325. bool Curve::mouseMove(int x, int y)
  326. {
  327. y = 255 - y;
  328. if ( is_mouse_down ) {
  329. if (current != points.end()) {
  330. int prev_x = 0;
  331. int next_x = 255;
  332. if (current != points.begin()) {
  333. int prev_y = (current - 1)->y;
  334. prev_x = (current - 1)->x;
  335. //match the previous point
  336. if ( points.size() > 2 && ::abs(x - prev_x) <= tolerance && ::abs(y - prev_y) <= tolerance ) {
  337. current--;
  338. current = points.erase(current);
  339. DEBUG_PRINT("erase previous");
  340. return true;
  341. }
  342. //if x less than x of previou point
  343. if ( x <= prev_x) {
  344. //DEBUG_PRINT("less than prev_x");
  345. return true;
  346. }
  347. }
  348. if ( ( current + 1) != points.end()) {
  349. int next_y = (current + 1)->y;
  350. next_x = (current + 1)->x;
  351. //match the next point
  352. if ( points.size() > 2 && ::abs(x - next_x) <= tolerance && ::abs(y - next_y) <= tolerance ) {
  353. current = points.erase(current);
  354. DEBUG_PRINT("erase next");
  355. return true;
  356. }
  357. //if x great than x of next point
  358. if ( x >= next_x) {
  359. //DEBUG_PRINT("large than next_x");
  360. return true;
  361. }
  362. }
  363. current->x = CLIP_RANGE(x, 0, 255);
  364. current->y = CLIP_RANGE(y, 0, 255);
  365. return true;
  366. }
  367. }
  368. return false;
  369. }
  370. void Curve::mouseUp(int x, int y)
  371. {
  372. y = 255 - y;
  373. is_mouse_down = false;
  374. }
  375. void Curve::clearPoints()
  376. {
  377. points.clear();
  378. }
  379. int Curve::addPoint(const Point &p)
  380. {
  381. vector<Point>::iterator iter = add(p.x, p.y);
  382. if ( iter != points.end() )
  383. return 1;
  384. else
  385. return 0;
  386. }
  387. int Curve::deletePoint(const Point &p)
  388. {
  389. vector<Point>::iterator iter;
  390. iter = find( p.x, p.y );
  391. if ( iter != points.end() ) {
  392. if ( current == iter )
  393. current = points.end();
  394. points.erase(iter);
  395. return 1;
  396. }
  397. return 0;
  398. }
  399. int Curve::movePoint(const Point &p, int x, int y)
  400. {
  401. vector<Point>::iterator iter;
  402. iter = find( p.x, p.y );
  403. if ( iter != points.end() ) {
  404. iter->x = x;
  405. iter->y = y;
  406. return 1;
  407. }
  408. return 0;
  409. }
  410. //=========================================================
  411. // Curves
  412. Curves::Curves()
  413. {
  414. CurrentChannel = &RGBChannel;
  415. }
  416. Curves::~Curves()
  417. {
  418. }
  419. void Curves::draw(Mat &mat)
  420. {
  421. if (CurrentChannel) CurrentChannel->draw(mat);
  422. }
  423. void Curves::mouseDown(int x, int y)
  424. {
  425. if (CurrentChannel) CurrentChannel->mouseDown(x, y);
  426. }
  427. bool Curves::mouseMove(int x, int y)
  428. {
  429. if (CurrentChannel)
  430. return CurrentChannel->mouseMove(x, y);
  431. return false;
  432. }
  433. void Curves::mouseUp(int x, int y)
  434. {
  435. if (CurrentChannel) CurrentChannel->mouseUp(x, y);
  436. }
  437. void Curves::createColorTables(uchar colorTables[][256])
  438. {
  439. double z[256];
  440. BlueChannel.calcCurve(z);
  441. for (int i = 0; i < 256; ++i ) {
  442. colorTables[0][i] = z[i];
  443. }
  444. GreenChannel.calcCurve(z);
  445. for (int i = 0; i < 256; ++i )
  446. colorTables[1][i] = z[i];
  447. RedChannel.calcCurve(z);
  448. for (int i = 0; i < 256; ++i ) {
  449. colorTables[2][i] = z[i];
  450. }
  451. uchar value;
  452. RGBChannel.calcCurve(z);
  453. for (int i = 0; i < 256; ++i ) {
  454. for (int c = 0; c < 3; c++ ) {
  455. value = colorTables[c][i];
  456. colorTables[c][i] = z[value];
  457. }
  458. }
  459. }
  460. int Curves::adjust(InputArray src, OutputArray dst, InputArray mask)
  461. {
  462. Mat input = src.getMat();
  463. if( input.empty() ) {
  464. return -1;
  465. }
  466. dst.create(src.size(), src.type());
  467. Mat output = dst.getMat();
  468. bool hasMask = true;
  469. Mat msk = mask.getMat();
  470. if (msk.empty())
  471. hasMask = false;
  472. const uchar *in;
  473. const uchar *pmask;
  474. uchar *out;
  475. int width = input.cols;
  476. int height = input.rows;
  477. int channels = input.channels();
  478. uchar colorTables[3][256];
  479. //create color tables
  480. createColorTables( colorTables );
  481. //adjust each pixel
  482. if ( hasMask ) {
  483. #ifdef HAVE_OPENMP
  484. #pragma omp parallel for
  485. #endif
  486. for (int y = 0; y < height; y ++) {
  487. in = input.ptr<uchar>(y);
  488. out = output.ptr<uchar>(y);
  489. pmask = msk.ptr<uchar>(y);
  490. for (int x = 0; x < width; x ++) {
  491. for (int c = 0; c < 3; c++) {
  492. *out = (colorTables[c][*in] * pmask[x] / 255.0)
  493. + (*in) * (255 - pmask[x]) / 255.0;
  494. out++; in++;
  495. }
  496. for (int c = 0; c < channels - 3; c++) {
  497. *out++ = *in++;
  498. }
  499. }
  500. }
  501. } else {
  502. #ifdef HAVE_OPENMP
  503. #pragma omp parallel for
  504. #endif
  505. for (int y = 0; y < height; y ++) {
  506. in = input.ptr<uchar>(y);
  507. out = output.ptr<uchar>(y);
  508. for (int x = 0; x < width; x ++) {
  509. for (int c = 0; c < 3; c++) {
  510. *out++ = colorTables[c][*in++];
  511. }
  512. for (int c = 0; c < channels - 3; c++) {
  513. *out++ = *in++;
  514. }
  515. }
  516. }
  517. }
  518. return 0;
  519. }
  520. } /* namespace cv */

参考

http://iyenn.com/rec/1661922.html

下载

源码下载

天天代码码天天
微信公众号
.NET 人工智能实践
注:本文转载自blog.csdn.net的天天代码码天天的文章"https://lw112190.blog.csdn.net/article/details/141137754"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top