5

I want to draw curve on control points so that I can move the curve to change the colours , below is the code , getting help from a very well explained answer

const int N=5;      // number of control points (must be >= 4)
float ctrl[N]=      // control points y values initiated with linear function y=x
{           // x value is index*1.0/(N-1)
    0.00,
    0.25,
    0.50,
    0.75,
    1.00,
 };
float correction(float col,float *ctrl,int n)
    {
    float di=1.0/float(n-1);
    int i0,i1,i2,i3;
    float t,tt,ttt;
    float a0,a1,a2,a3,d1,d2;
    // find start control point
    col*=float(n-1);
    i1=col; col-=i1;
    i0=i1-1;
    i2=i1+1; if (i2>=n) i2=n-1;
    i3=i1+2;
    // compute interpolation coefficients
    if (i0>=0) d1=0.5*(ctrl[i2]-ctrl[i0]); else d1=ctrl[i2]-ctrl[i1];
    if (i3< n) d2=0.5*(ctrl[i3]-ctrl[i1]); else d2=ctrl[i2]-ctrl[i1];
    a0=ctrl[i1];
    a1=d1;
    a2=(3.0*(ctrl[i2]-ctrl[i1]))-(2.0*d1)-d2;
    a3=d1+d2+(2.0*(-ctrl[i2]+ctrl[i1]));
    // now interpolate new colro intensity
    t=col; tt=t*t; ttt=tt*t;
    t=a0+(a1*t)+(a2*tt)+(a3*ttt);
    return t;
    }




int main (int argc, const char** argv)
{
Mat input = imread ("E:\\img2.jpg");
Mat input1 = input;
for(int i=0 ; i<input1.rows ; i++)
{
    for (int p=0;p<input1.cols;p++)
    {

        input1.at<cv::Vec3b>(i,p)[0] = 255*correction(input1.at<cv::Vec3b>(i,p)[0]/255.0,ctrl,N);  //B
        input1.at<cv::Vec3b>(i,p)[1] = 255*correction(input1.at<cv::Vec3b>(i,p)[1]/255.0,ctrl,N);  //G
        input1.at<cv::Vec3b>(i,p)[2] = 255*correction(input1.at<cv::Vec3b>(i,p)[2]/255.0,ctrl,N);  //R

    }
}

imshow("image" , input);
waitKey();

}

But the required output is like the curve the program is working , but the curves are not drawing on my screen like below , how to draw them using opencv or other approach So that these lines can play the role of their specific colour in image and with their values , like below right one is the orignal image and left one is the result of changing values through cuves , below curves are the control points per B,G,R

enter image description here

5
  • Okay. What is your actual question? Is there something wrong with the curves? Are they not smooth enough (you might want to increase the number of control points for that). Commented May 14, 2014 at 5:58
  • no , actual question is that the program is working , but the curves are not drawing on my screen , how to draw them using opencv or other approach Commented May 14, 2014 at 8:40
  • hmm. but we do see curves there, no ? how did you draw those ? Commented May 14, 2014 at 8:44
  • that's not drawn by me :( , that was from other question , that man which I linked above uses other tool Commented May 14, 2014 at 8:47
  • he uses Simple for (t=0;t<=1;t+=0.01) loop with Canvas->LineTo(t,correction(t,ctrl,5)); but i saw only createTrackbar in opencv Commented May 14, 2014 at 8:49

1 Answer 1

12

This code sketch allows you to edit spline with mouse it uses the files from this link (attach to your project: overhauser.cpp overhauser.hpp and vec3.hpp):

Left mouse button adds/moves a point, right removes.

enter image description here

#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/opencv.hpp"
#include <iostream>
#include <fstream>
#include "overhauser.hpp"

using namespace std;
using namespace cv;

Mat result;
Mat Img;

int current_color=0;

vector<cv::Point2f> pts_red;
vector<cv::Point2f> pts_green;
vector<cv::Point2f> pts_blue;

Mat curvesImg;
int selectedPt=-1;

CRSpline* spline_red = 0;
CRSpline* spline_green = 0;
CRSpline* spline_blue = 0;

unsigned char LUT_RED[256];
unsigned char LUT_GREEN[256];
unsigned char LUT_BLUE[256];

// comparison function:
bool mycomp (Point2f p1, Point2f p2)
{
    return p1.x<p2.x;
}

float dist(Point2f p1,Point2f p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

int findNEarestPt(Point2f pt, float maxDist)
{   
    vector<Point2f> current_pts_set;

    current_color=0;

    if(pt.x>255 && pt.x<512)
    {
        current_color=1;
    }

    if(pt.x>=512)
    {
        current_color=2;
    }

    float ptx=pt.x;

    switch(current_color)
    {
    case 0:
        current_pts_set=pts_red;
        break;
    case 1:
        current_pts_set=pts_green;
        pt.x-=255;
        break;
    case 2:
        current_pts_set=pts_blue;
        pt.x-=511;
        break;
    }

    float minDist=FLT_MAX;
    int ind=-1;
    for(int i=0;i<current_pts_set.size();++i)
    {
        float d=dist(pt,current_pts_set[i]);
        if(minDist>d)
        {
            ind=i;
            minDist=d;
        }
    }
    if(minDist>maxDist)
    {
        ind=-1;
    }

    return ind;
}

float F(float t,float x, CRSpline* spline)
{
    vec3 rv = spline->GetInterpolatedSplinePoint(t);
    return x-rv.x;
}

float solveForX(float x,CRSpline* slpine)
{
    float a=-1.0f,b=1.0,c,e=1e-2;
    c=(a+b)/2;
    while( (fabs(b-a)>e) && (F(c,x,slpine)!=0) )
    {
        if (F(a,x,slpine)*F(c,x,slpine)<0)
        {
            b=c;
        }
        else
        {
            a=c;
        }
        c=(a+b)/2;
    }
    return c;
}


int ind=-1;

void mouseHandler(int event, int x, int y, int flags, void* param)
{
    Point2f m;
    m.x=x;
    m.y=y;
    curvesImg=Scalar(0,0,0);

    switch (event)
    {
    case cv::EVENT_RBUTTONDOWN:
        ind=findNEarestPt(m,5);
        if (ind==-1)
        {

        }else
        {
            switch(current_color)
            {
            case 0:
                pts_red.erase(pts_red.begin()+ind);
                break;
            case 1:
                pts_green.erase(pts_green.begin()+ind);
                break;
            case 2:
                pts_blue.erase(pts_blue.begin()+ind);
                break;
            }
            ind=-1;
        }
        break;

    case cv::EVENT_LBUTTONDOWN:
        ind=findNEarestPt(m,5);
        if (ind==-1)
        {
            switch(current_color)
            {
            case 0:
                pts_red.push_back(m);
                selectedPt=pts_red.size()-1;
                break;
            case 1:

                pts_green.push_back(Point2f(m.x-255.0,m.y));
                selectedPt=pts_green.size()-1;
                break;
            case 2:
                pts_blue.push_back(Point2f(m.x-511,m.y));
                selectedPt=pts_blue.size()-1;
                break;
            }
        }else
        {
            selectedPt=ind;
        }
        break;

    case cv::EVENT_MOUSEMOVE:
        if(ind!=-1)
        {
            switch(current_color)
            {
            case 0:
                pts_red[selectedPt].x=m.x;
                pts_red[selectedPt].y=m.y;
                break;
            case 1:
                pts_green[selectedPt].x=m.x-255;
                pts_green[selectedPt].y=m.y;
                break;
            case 2:
                pts_blue[selectedPt].x=m.x-511;
                pts_blue[selectedPt].y=m.y;
                break;
            }
        }
        break;
    case cv::EVENT_LBUTTONUP:
        ind=-1;
        break;
    }

    std::sort(pts_red.begin(),pts_red.end(),mycomp);
    if(pts_red.size()>0)
    {
        pts_red[pts_red.size()-1].x=255;
        pts_red[0].x=0;
    }

    std::sort(pts_green.begin(),pts_green.end(),mycomp);
    if(pts_green.size()>0)
    {
        pts_green[pts_green.size()-1].x=255;
        pts_green[0].x=0;
    }

    std::sort(pts_blue.begin(),pts_blue.end(),mycomp);
    if(pts_blue.size()>0)
    {
        pts_blue[pts_blue.size()-1].x=255;
        pts_blue[0].x=0;
    }

    for(int i=0;i<pts_red.size();++i)
    {
        circle(curvesImg,pts_red[i],5,Scalar(0,0,255),-1,CV_AA);
    }

    for(int i=0;i<pts_green.size();++i)
    {
        circle(curvesImg,Point2f(pts_green[i].x+255,pts_green[i].y),5,Scalar(0,255,0),-1,CV_AA);
    }

    for(int i=0;i<pts_blue.size();++i)
    {
        circle(curvesImg,Point2f(pts_blue[i].x+511,pts_blue[i].y),5,Scalar(255,0,0),-1,CV_AA);
    }

    if (spline_red) {delete spline_red;}
    spline_red = new CRSpline();

    if (spline_green) {delete spline_green;}
    spline_green = new CRSpline();

    if (spline_blue) {delete spline_blue;}
    spline_blue = new CRSpline();

    for (int i=0;i<pts_red.size();++i)
    {
        vec3 v(pts_red[i].x,pts_red[i].y,0);
        spline_red->AddSplinePoint(v);
    }

    for (int i=0;i<pts_green.size();++i)
    {
        vec3 v(pts_green[i].x,pts_green[i].y,0);
        spline_green->AddSplinePoint(v);
    }

    for (int i=0;i<pts_blue.size();++i)
    {
        vec3 v(pts_blue[i].x,pts_blue[i].y,0);
        spline_blue->AddSplinePoint(v);
    }

    vec3 rv_last(0,0,0);
    if(pts_red.size()>2)
    {
        for(int i=0;i<256;++i)
        {
            float t=solveForX(i,spline_red);
            vec3 rv = spline_red->GetInterpolatedSplinePoint(t);
            if(rv.y>255){rv.y=255;}
            if(rv.y<0){rv.y=0;}
            unsigned char I=(unsigned char)(rv.y);
            LUT_RED[i]=255-I;
            if(i>0)
            {
                line(curvesImg,Point(rv.x,rv.y),Point(rv_last.x,rv_last.y),Scalar(0,0,255),1);
            }
            rv_last=rv;
        }
    }
    rv_last=vec3(0,0,0);
    if(pts_green.size()>2)
    {
        for(int i=0;i<256;++i)
        {
            float t=solveForX(i,spline_green);
            vec3 rv = spline_green->GetInterpolatedSplinePoint(t);
            if(rv.y>255){rv.y=255;}
            if(rv.y<0){rv.y=0;}
            unsigned char I=(unsigned char)(rv.y);
            LUT_GREEN[i]=255-I;
            if(i>0)
            {
                line(curvesImg,Point(rv.x+255,rv.y),Point(rv_last.x+255,rv_last.y),Scalar(0,255,0),1);
            }
            rv_last=rv;
        }
    }
    rv_last=vec3(0,0,0);
    if(pts_blue.size()>2)
    {
        for(int i=0;i<256;++i)
        {
            float t=solveForX(i,spline_blue);
            vec3 rv = spline_blue->GetInterpolatedSplinePoint(t);
            if(rv.y>255){rv.y=255;}
            if(rv.y<0){rv.y=0;}
            unsigned char I=(unsigned char)(rv.y);
            LUT_BLUE[i]=255-I;
            if(i>0)
            {
                line(curvesImg,Point(rv.x+511,rv.y),Point(rv_last.x+511,rv_last.y),Scalar(255,0,0),1);
            }
            rv_last=rv;
        }

    }

    int cur_col=0;

    if(m.x>255 && m.x<512)
    {
        cur_col=1;
    }

    if(m.x>=512)
    {
        cur_col=2;
    }

    Scalar col;
    switch(cur_col)
    {
    case 0:
        col=Scalar(0,0,255);
        break;
    case 1:
        col=Scalar(0,255,0);
        break;
    case 2:
        col=Scalar(255,0,0);
        break;
    }
    line(curvesImg,Point(0,m.y),Point(curvesImg.cols,m.y),col,1);
    line(curvesImg,Point(m.x,0),Point(m.x,curvesImg.rows),col,1);

    imshow("Correction curves",curvesImg);  

    vector<Mat> ch;
    cv::split(Img,ch);
    LUT(ch[0],Mat(256,1,CV_8UC1,LUT_BLUE),ch[0]);
    LUT(ch[2],Mat(256,1,CV_8UC1,LUT_RED),ch[2]);
    LUT(ch[1],Mat(256,1,CV_8UC1,LUT_GREEN),ch[1]);
    cv::merge(ch,result);

    imshow("Transformed",result);   
}
// ---------------------------------
// 
// ---------------------------------
//==============================================================================

int main( int argc, char** argv )
{

    for (int i=0;i<256;++i)
    {
        LUT_RED[i]=i;
        LUT_GREEN[i]=i;
        LUT_BLUE[i]=i;
    }

    namedWindow("Image");
    namedWindow("Correction curves");
    namedWindow("Transformed");

    Img=imread("D:\\ImagesForTest\\lena.jpg",1);

    imshow("Image",Img);

    curvesImg=Mat::zeros(256,768,CV_8UC3);
    setMouseCallback("Correction curves", mouseHandler, NULL);
    waitKey(0);

    getchar();
}
Sign up to request clarification or add additional context in comments.

14 Comments

berak i know you will :P , i guess it before your vote
Thanks :). It seems that I should swap x and y axis.
@AndreySmorodov which is the best way to follow to get a strong hold on color ? the way i follow above in question is the cubic and your one is the Catmull-Rom ?
The thing i am saying is look in your resultant image , there are two shape , one is original (without red) and one which is following the curves and colored , so if i have the right one image (without red) and i want to convert it into left one (red coloured) with curves once but when i get it through curve,i want to save that values of curve and then next time i only multiply that value with the image to get the resultant image without drawing curves,like we did for sepia filter we multiply .131,.534,.272, .168,.686,.349, .189,.769,.393; these values with original image we wil get sepia
Ough :) Just replicate it 3 times :). I've made it for you.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.