c++ - OpenCV - Fit a curve to a set of points -
this follows post here: opencv - remove "white" artifacts image , fit curve
i removed extraneous white points in image looking points across diagonal @ given location. result looks this:
now, fit curve remaining points in image. have been looking through previous posts in opencv have suggested approxpolydp
. there simpler way of fitting curve , displaying in opencv?
the idea here using hough curves little elaborate me since image binary: http://homepages.inf.ed.ac.uk/rbf/books/bandb/lib/bandb4_3.pdf
the final image (0-255) grayscale image of w256 x h1024
.
edit
i connected points in image using line segments. however, connect points fitting smooth curve of them. have searched such method , not find way.
i think catmul-rom spline choice task.
you can find implementation here: http://www.codeproject.com/articles/30838/overhauser-catmull-rom-splines-for-camera-animatio
answer ahf's comment (put here qix advice):
this code sketch allows edit spline mouse uses files this link (attach project: overhauser.cpp overhauser.hpp , vec3.hpp):
left mouse button adds/moves point, right removes.
the code not difficult, i've made 1-channel modification (for compactness).
i guess you'll catch idea.
#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; vector<cv::point2f> pts; mat curvesimg; int selectedpt=-1; crspline* spline = 0; unsigned char lut_red[256]; // case-insensitive 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) { float mindist=flt_max; int ind=-1; for(int i=0;i<pts.size();++i) { float d=dist(pt,pts[i]); if(mindist>d) { ind=i; mindist=d; } } if(mindist>maxdist) { ind=-1; } return ind; } float f(float t,float x) { vec3 rv = spline->getinterpolatedsplinepoint(t); return x-rv.x; } float solveforx(float x) { float a=0,b=1.0,c,e=1e-5; c=(a+b)/2; while( (fabs(b-a)>e) && (f(c,x)!=0) ) { if (f(a,x)*f(c,x)<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 { pts.erase(pts.begin()+ind); ind=-1; } break; case cv::event_lbuttondown: ind=findnearestpt(m,5); if (ind==-1) { pts.push_back(m); selectedpt=pts.size()-1; }else { selectedpt=ind; } break; case cv::event_mousemove: if(ind!=-1) { pts[selectedpt].x=m.x; pts[selectedpt].y=m.y; } break; case cv::event_lbuttonup: ind=-1; break; } std::sort(pts.begin(),pts.end(),mycomp); if(pts.size()>0) { pts[pts.size()-1].x=curvesimg.cols; pts[0].x=0; } for(int i=0;i<pts.size();++i) { circle(curvesimg,pts[i],5,scalar(0,255,255),-1,cv_aa); } if (spline) {delete spline;} spline = new crspline(); (int i=0;i<pts.size();++i) { vec3 v(pts[i].x,pts[i].y,0); spline->addsplinepoint(v); } vec3 rv_last(0,0,0); if(pts.size()>2) { for(int i=0;i<256;++i) { float t=solveforx(i); vec3 rv = spline->getinterpolatedsplinepoint(t); unsigned char i=(unsigned char)(rv.y); lut_red[i]=255-i; if(i>1) { line(curvesimg,point(rv.x,rv.y),point(rv_last.x,rv_last.y),scalar(0,0,255),1); } rv_last=rv; } } line(curvesimg,point(0,m.y),point(curvesimg.cols,m.y),scalar(0,255,0),1); line(curvesimg,point(m.x,0),point(m.x,curvesimg.rows),scalar(0,255,0),1); imshow("result",curvesimg); vector<mat> ch; cv::split(img,ch); lut(ch[2],mat(256,1,cv_8uc1,lut_red),ch[2]); cv::merge(ch,result); imshow("transformed",result); } // --------------------------------- // // --------------------------------- //============================================================================== int main( int argc, char** argv ) { (int i=0;i<256;++i) { lut_red[i]=i; } namedwindow("image",cv::window_normal); namedwindow("result"); namedwindow("transformed"); img=imread("d:\\imagesfortest\\lena.jpg",1); imshow("image",img); curvesimg=mat::zeros(256,256,cv_8uc3); setmousecallback("result", mousehandler, null); waitkey(0); getchar(); }
Comments
Post a Comment