2014-04-06 5 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

Окончательное изображение является (0-255) полутоновое изображение w256 x h1024.

РЕДАКТИРОВАТЬ

Я просто соединил точки на изображении с помощью отрезков. Тем не менее, я хотел бы соединить точки, установив гладкую кривую для всех них. Я искал SO для такого метода и не смог найти способ.

connect

+0

См [approxPolyDP] (http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.html) может быть полезным. – Haris

+0

«Гладкость» подразумевает (а) наличие некоторой гипотезы о процессе, который генерирует эти точки, - есть ли у вас физическая модель? и за «шум»/«ошибки», связанные с ними (их отклонение от предполагаемой модели)? (b) наличие некоторого приложения для кривой - создание красивой картинки для просмотра - это приложение, но, возможно, у вас есть определенные потребности в интерполяции/экстраполяции из ваших образцов и модели? Вам необходимо ответить как (a), так и (b), чтобы добиться прогресса. –

+0

@Haris Я попытался использовать findContours и approxPolyDP для моего кода. Однако я не мог заставить его работать из-за ошибок доступа. – Eagle

ответ

2

Я думаю, что catmul-ром сплайн будет хорошим выбором для вашей задачи.

Вы можете найти реализацию здесь: http://www.codeproject.com/Articles/30838/Overhauser-Catmull-Rom-Splines-for-Camera-Animatio

Ответ на комментарий AHF в (поставить его здесь советами Qix):

Этот код эскиза позволяет редактировать сплайн с помощью мыши он использует файлы this link (приложите к вашему проекту: overhauser.cpp overhauser.hpp и vec3.hpp):

Левая кнопка мыши добавляет/перемещает точку, справа удаляет.

Код не очень сложный, поэтому я сделал одноканальную модификацию (для компактности).

Я думаю, вы поймаете эту идею.

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

Смежные вопросы