2013-05-16 73 views
7

是否有解決方案來訪問沿着曲線/路徑的像素?我們可以使用LineIterator來做它使用opencv訪問沿着曲線/路徑的像素

+1

的可能重複的[OpenCV的 - 訪問沿曲線/路徑像素](HTTP:/ /stackoverflow.com/questions/5078387/opencv-access-to-pixels-along-the-curve-path) –

+0

你從哪裏得到曲線/路徑?或者你允許哪種方式?多項式?樣條曲線? – Micka

回答

4

好的,這裏是一種訪問像素的方法,可以連接一個可以參數化的曲線。可能會有更高效的方法,但這個很簡單:只在參數步驟中對曲線進行採樣,以便不會訪問像素兩次,也不會跳過像素:

我已經從參數函數維基百科作爲樣品: http://en.wikipedia.org/wiki/Parametric_equation#Some_sophisticated_functions

enter image description here

int main() 
{ 
cv::Mat blank = cv::Mat::zeros(512,512,CV_8U); 

// parametric function: 
// http://en.wikipedia.org/wiki/Parametric_equation#Some_sophisticated_functions 
// k = a/b 
// x = (a-b)*cos(t) + b*cos(t((a/b)-1)) 
// y = (a-b)*sin(t) - b*sin(t((a/b)-1)) 

float k = 0.5f; 
float a = 70.0f; 
float b = a/k; 

// translate the curve somewhere 
float centerX = 256; 
float centerY = 256; 

// you will check whether the pixel position has moved since the last active pixel, so you have to remember the last one: 
int oldpX,oldpY; 
// compute the parametric function's value for param t = 0 
oldpX = (a-b)*cos(0) + b*cos(0*((a/b)-1.0f)) + centerX -1; 
oldpY = (a-b)*sin(0) - b*sin(0*((a/b)-1.0f)) + centerY -1; 

// initial stepsize to parametrize the curve 
float stepsize = 0.01f; 

//counting variables for analyzation 
unsigned int nIterations = 0; 
unsigned int activePixel = 0; 

// iterate over whole parameter region 
for(float t = 0; t<4*3.14159265359f; t+= stepsize) 
{ 
    nIterations++; 

    // compute the pixel position for that parameter 
    int pX = (a-b)*cos(t) + b*cos(t*((a/b)-1.0f)) + centerX; 
    int pY = (a-b)*sin(t) - b*sin(t*((a/b)-1.0f)) + centerY; 

    // only access pixel if we moved to a new pixel: 
    if((pX != oldpX)||(pY != oldpY)) 
    { 
     // if distance to old pixel is too big: stepsize was too big 
     if((abs(oldpX-pX)<=1) && (abs(oldpY-pY)<=1)) 
     { 
      //--------------------------------------------------------------- 
      // here you can access the pixel, it will be accessed only once for that curve position! 
      blank.at<unsigned char>((pY),(pX)) = blank.at<unsigned char>((pY),(pX))+1; 
      //--------------------------------------------------------------- 

      // update last position 
      oldpX = pX; 
      oldpY = pY; 

      activePixel++; // count number of pixel on the contour 
     } 
     else 
     { 
      // adjust/decrease stepsize here 
      t -= stepsize; 
      stepsize /= 2.0f; 

      //TODO: choose smarter stepsize updates 
     } 
    } 
    else 
    { 
     // you could adjust/increase the stepsize here 
     stepsize += stepsize/2.0f; 

     //TODO: prevent stepsize from becoming 0.0f !! 
     //TODO: choose smarter stepsize updates 
    } 

} 
std::cout << "nIterations: " << nIterations << " for activePixel: " << activePixel << std::endl; 

cv::imwrite("accessedOnce.png", blank>0); 
cv::imwrite("accessedMulti.png", blank>1); 

cv::waitKey(-1); 
return 0; 
} 

給出以下結果:

像素訪問一次:

enter image description here

像素訪問不止一次:

enter image description here

終端輸出: nIterations: 1240 for activePixel: 1065

+0

我們可以使用鼠標使用opencv移動曲線嗎? – AHF

+0

@AHF移動曲線是什麼意思? openCV有一些使用鼠標輸入的接口。但是我的算法是用於「訪問」(意思是自動處理)每個像素的參數化(f(t))曲線。 – Micka

+0

像我這裏陳述http://stackoverflow.com/questions/23641208/how-to-draw-curve-on-control-points-using-opencv我需要繪製三個曲線的RGB和移動他們的曲線,萬物工作很好,但繪製曲線移動鼠標正在爲我創造問題,因爲我沒有在互聯網上得到很多很好的例子 – AHF

4

我不認爲有任何內置的功能這一點。您需要首先在cv::Mat結構中定義線條/曲線,然後從那裏繼續。讓我用一個例子來解釋。

  1. 你有一個形象,cv::Mat input_image並使用一個cv::HoughLinesDetector來檢測其存儲在cv::Mat hough_lines圖像中的線條。
  2. 然後,您將需要通過hough_lines迭代和填充cv::Mat hough_Mat(cv::Size(input_image.size()))(如果你想明亮的展示你的線條與原數據應轉換爲BGR圖像。
  3. 然後,只需通過hough_Mat迭代的哪些像素以上零,然後就訪問input_image同一位置。

雖然這個例子是一個簡單的使用Hough變換,你可以與任何其他曲線使用它,只要你有曲線的數據WRT原始圖像。

HTH