2014-04-06 78 views
4

這裏在此之前,我的帖子:OpenCV - Remove "white" artifacts from image and fit a curveOpenCV的 - 曲線擬合到一組點

我通過在任何給定的位置尋找的對角線點去除圖像中的多餘的白點。我的結果現在看起來是這樣的:

remove diag

現在,我想將曲線擬合到圖像中的剩餘點。我一直在瀏覽OpenCV的以前的帖子,其中一些人建議approxPolyDP。是否有更簡單的方法來擬合曲線並在OpenCV中顯示它?

這裏使用霍夫曲線的想法是有點太複雜了我,因爲我的形象基本上是二進制:http://homepages.inf.ed.ac.uk/rbf/BOOKS/BANDB/LIB/bandb4_3.pdf

最終圖像是的w256 x h1024(0-255)灰度圖像。

EDIT

我只是用線段連接點在圖像中。但是,我想通過爲所有這些點擬合平滑曲線來連接這些點。我曾經搜索過這種方法,但找不到方法。

connect

+0

參見[approxPolyDP(http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.html)可能會有所幫助。 – Haris

+0

「平滑」意味着(a)對產生這些點的過程有一些假設 - 您是否有物理模型?以及與它們相關的「噪音」/「誤差」(它們與假設模型的偏差)? (b)在曲線中考慮一些應用程序 - 生成漂亮的圖片以查看是一個應用程序,但也許您有一些特定的需求來從樣本和模型中進行插值/外插? 您需要回答(a)和(b)以取得進展。 –

+0

@哈里斯我嘗試使用findContours和approxPolyDP到我的代碼。但是,由於訪問衝突錯誤,我無法工作。 – Eagle

回答

2

我認爲catmul-ROM花將是你的任務是不錯的選擇。

你可以找到執行此: http://www.codeproject.com/Articles/30838/Overhauser-Catmull-Rom-Splines-for-Camera-Animatio

回答AHF的評論(把它放在這裏通過的Qix建議):

此代碼草圖允許你編輯用鼠標花從使用的文件this link(附加到您的項目:overhauser.cpp overhauser.hpp和vec3.hpp):

鼠標左鍵添加/移動一個點,右鍵刪除。

代碼不是很困難,所以我做了1通道修改(爲了緊湊)。

我想你會接受這個想法。

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; 

vector<cv::Point2f> pts; 
Mat curvesImg; 
int selectedPt=-1; 
CRSpline* spline = 0; 

unsigned char LUT_RED[256]; 

// a 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(); 

    for (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) 
{ 

    for (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(); 
} 
+0

但是當我們完成代碼時,有沒有什麼函數可以通過它來移動BGR的曲線? – AHF

+0

我不知道你的問題,你可以重新制定它嗎。 –

+0

你給我同樣的建議,所以從這我談論這個scenerio http://stackoverflow.com/questions/23641208/how-to-draw-curve-on-control-points-using-opencv – AHF