2013-05-18 2 views
3

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

enter image description here

Этот код заканчивается после добавления некоторых точек .Я не нашел решение для этого.

#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/imgproc/imgproc_c.h" 
#include <opencv2/legacy/compat.hpp> 
#include <opencv2/core/core.hpp> 
#include <iostream> 
#include <cmath> 
#include <list> 
using namespace cv; 
using namespace std; 

    //this method to find the 8-neighbors of a point from image 
vector<Point> search8Neighbor(cv::Mat mat,Point startPoint) 
{ 
    vector<Point> segment; 
    Point p; 
    //uchar p1 = mat.at<uchar>(startPoint.x, startPoint.y); 
    uchar p2 = mat.at<uchar>(startPoint.x-1, startPoint.y); 
    uchar p3 = mat.at<uchar>(startPoint.x-1, startPoint.y+1); 
    uchar p4 = mat.at<uchar>(startPoint.x, startPoint.y+1); 
    uchar p5 = mat.at<uchar>(startPoint.x+1, startPoint.y+1); 
    uchar p6 = mat.at<uchar>(startPoint.x+1, startPoint.y); 
    uchar p7 = mat.at<uchar>(startPoint.x+1, startPoint.y-1); 
    uchar p8 = mat.at<uchar>(startPoint.x, startPoint.y-1); 
    uchar p9 = mat.at<uchar>(startPoint.x-1, startPoint.y-1); 

    //if(p1==255) segment.push_back(startPoint.x, startPoint.y); 
    if (p2 == 255) { 
      p.x=startPoint.x-1; 
      p.y=startPoint.y; 
      segment.push_back(p); 
    } 
    if(p3==255) { 
      p.x=startPoint.x-1; 
      p.y=startPoint.y+1; 
      segment.push_back(p); 
    } 

    if(p4==255) { 
      p.x=startPoint.x; 
      p.y=startPoint.y+1; 
      segment.push_back(p); 
    } 

    if(p5==255) { 
      p.x=startPoint.x+1; 
      p.y=startPoint.y+1; 
      segment.push_back(p); 
    } 

    if(p6==255) { 
      p.x=startPoint.x+1; 
      p.y=startPoint.y; 
      segment.push_back(p); 
    } 
    if(p7==255) { 
      p.x=startPoint.x+1; 
      p.y=startPoint.y-1; 
      segment.push_back(p); 
    } 
    if(p8==255){ 
      p.x=startPoint.x; 
      p.y=startPoint.y-1; 
      segment.push_back(p); 
    } 

    if(p9==255) { 
      p.x=startPoint.x-1; 
      p.y=startPoint.y-1; 
      segment.push_back(p); 
    } 

    return segment ; 

} 
    //this method return a vector of points from a skeleton that contains all the points 
// between a start point "peak" and an end point 
//this method use the idea of Breadth first search 
    vector<Point> traceLine(Mat img , Point peak) 
{ 
    vector<Point> vect1; 
    vector<Point> vect2; 
    img.at<uchar>(peak.x,peak.y)=0;// 
    vect1.push_back(peak);//add peak to vect1 
    while(vect1.size() != 0) 
     { 
     Point p=vect1[0]; 
     vect1.erase(vect1.begin()); 
     vect2.push_back(p); 
     vector<Point> vectN; 
     vectN=search8Neighbor(img,p); 
     vector<Point>::iterator it; 
     it = vect1.begin(); 
     //cout<<vectN.size()<<endl; 
     for(int i=0;i<vectN.size();i++) 
      { 
       img.at<uchar>(vectN[i].x,vectN[i].y)=0; 
       vect1.insert(it,vectN[i]); 

      } 
     } 
return vect2; 
} 

int main(int argc, char** argv) 
{ 
cv::Mat im = cv::imread("aa.jpg",0); 
if (im.empty()) 
return -1; 
cv::Mat img; 
cv::threshold(im, img, 155, 255, CV_THRESH_BINARY); 
vector<Point> vect1; 
Point p; 
p.x=20; 
p.y=30; 
if(mat.at<uchar>(p.x-1, p.y)==255) 
vect1=traceLine(img,p); 
imshow("image",im); 
cv::waitKey(); 
return 0 ; 
} 

ответ

2

циновка индексируется в обычном порядке строк/COL для матриц, так что вы хотите mat.at<uchar>(y, x), не mat.at<uchar>(x, y), или путаница приведет.

Где у вас есть:

vector<Point>::iterator it; 
it = vect1.begin(); 
... 
for(...) 
    vect1.insert(it,vectN[i]); 

это сломается, если вставка вызывает буфер будет перераспределено, потому что тогда указует на какой-то памяти, которая была перераспределена, или, возможно, перераспределяется к чему-то еще. Вместо этого используйте

vect1.insert(vect1.begin(),vectN[i]); 

(который даст несколько иной порядок, что, кажется, делает ваша программа) или использовать push_back() на самом деле получить ширину первого поведения.

Самая большая проблема в поиске8Neighbor(). Где у вас есть uchar p2 = mat.at<uchar>(startPoint.x-1, startPoint.y); Что произойдет, если startPoint ссылается на пиксель на краю изображения? Вы будете ссылаться на пиксели вне изображения, и программа будет блуждать до тех пор, пока не произойдет исключение. Здесь вам нужно проверить, где вы находитесь, и не включать пиксели из-за пределов изображения по соседству.

EDIT Я не считал, что код не будет работать, если изменить, как я уже сказал. я реализовал исправления, и она работает:

#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/imgproc/imgproc_c.h" 
#include <opencv2/legacy/compat.hpp> 
#include <opencv2/core/core.hpp> 
#include <iostream> 
#include <cmath> 
#include <list> 
using namespace cv; 
using namespace std; 

// Find the 8-neighbors of a point from image. 
vector<Point> search8Neighbor(cv::Mat mat,Point startPoint) 
{ 
    vector<Point> neighbors; 
    vector<Point> offsets; 
    offsets.push_back(Point(-1, 0)); // p2 
    offsets.push_back(Point(-1, 1)); // p3 
    offsets.push_back(Point(0, 1)); // p4 
    offsets.push_back(Point(1, 1)); // p5 
    offsets.push_back(Point(1, 0)); // p6 
    offsets.push_back(Point(1, -1)); // p7 
    offsets.push_back(Point(0, -1)); // p8 
    offsets.push_back(Point(-1, -1)); // p9 

    vector<Point>::iterator it; 
    for(it = offsets.begin(); it < offsets.end(); ++it) 
    { 
     if(!((it->x < 0 && startPoint.x == 0) 
      || (it->y < 0 && startPoint.y == 0) 
      || (it->x > 0 && startPoint.x == mat.cols - 1) 
      || (it->y > 0 && startPoint.y == mat.rows - 1))) 
     { 
      Point p(startPoint + *it); 
      if(mat.at<uchar>(p) == 255) 
       neighbors.push_back(p); 
     } 
    } 

    return neighbors; 
} 

//this method return a vector of points from a skeleton that contains all the points 
// between a start point "peak" and an end point 
//this method use the idea of Breadth first search 
    vector<Point> traceLine(Mat img , Point peak) 
{ 
    vector<Point> vect1; 
    vector<Point> vect2; 
    img.at<uchar>(peak.y, peak.x)=0;// 
    vect1.push_back(peak);//add peak to vect1 
    while(vect1.size() != 0) 
     { 
     Point p=vect1[0]; 
     vect1.erase(vect1.begin()); 
     vect2.push_back(p); 
     vector<Point> vectN; 
     vectN = search8Neighbor(img, p); 

     //cout<< " vectN.size()=" << vectN.size()<<endl; 

     for(int i = 0; i < int(vectN.size()); ++i) 
      { 
       img.at<uchar>(vectN[i].y, vectN[i].x)=0; 
       vect1.push_back(vectN[i]); 
      } 
     } 
    return vect2; 
} 

int main(int argc, char** argv) 
{ 
    cv::Mat im = cv::imread("aa.jpg",0); 
    if (im.empty()) 
     return -1; 
    cv::Mat img; 
    cv::threshold(im, img, 155, 255, CV_THRESH_BINARY); 
    imshow("thresholded image",im); 
    vector<Point> vect1; 

    Point p(3, 32); 
    uchar u = img.at<uchar>(p.x, p.y); 
    if(img.at<uchar>(p) == 255) 
     vect1 = traceLine(img, p); 

    Mat output(im.rows, im.cols, CV_8UC3, Scalar(0, 0, 0)); 
    vector<Point>::iterator it; 

    for(it = vect1.begin(); it < vect1.end(); ++it) 
    { 
     Vec3b green(0, 255, 0); 
     output.at<Vec3b>(*it) = green; 
    } 
    imshow("output", output); 
    cv::waitKey(); 
    return 0 ; 
} 
+0

Большое спасибо за ваш ответ, я думаю, что есть проблема где-то в алгоритме, потому что я изменил его, как вы поручили мне, но он не работает, как я надеюсь, в любом случае большое спасибо за ваше руководство. – user138957

+1

Идея звуковая - если вы найдете все ошибки, которые она будет работать – Bull

+0

Это работает как шарм, спасибо большое :) – user138957

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