2016-04-18 32 views
0
int main() 
{ 

vector<vector<Point>> contours; 
vector<Vec4i> hierarchy; 
int largest_area=0; 
int largest_contour_index=0; 


OriginalImage = imread("C:\\Data Drive\\opencv Projects\\testwithC++\\Plant001-9\\SideView90\\Day_021.png",CV_LOAD_IMAGE_GRAYSCALE); 
BackgroundImage = imread("C:\\Data Drive\\opencv Projects\\testwithC++\\Plant001-9\\SideView90\\Day_001.png",CV_LOAD_IMAGE_GRAYSCALE); 

absdiff(OriginalImage,BackgroundImage,GrayImage); 
threshold(GrayImage,Binary,80,255,CV_THRESH_BINARY); 


namedWindow("OriginalImage", WINDOW_NORMAL);    
imshow("OriginalImage", OriginalImage);     


namedWindow("BackgroundImage", WINDOW_NORMAL);    
imshow("BackgroundImage", BackgroundImage);     

namedWindow("GrayImage", WINDOW_NORMAL);    
imshow("GrayImage", GrayImage);       


namedWindow("Binary", WINDOW_NORMAL);    
imshow("Binary", Binary);     

ImageROI = Binary(Rect(300,0,Binary.size().width-600,Binary.size().height)); 

namedWindow("ImageROI", WINDOW_NORMAL);     
imshow("ImageROI", ImageROI);       

dilate(ImageROI,BinaryMorph,Mat(),Point(-1,-1),2); 

namedWindow("BinaryMorph", WINDOW_NORMAL);    
imshow("BinaryMorph", BinaryMorph);     

findContours(BinaryMorph, contours, hierarchy, RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 

for(int i = 0; i< contours.size(); i++) 
{ 
    double a=contourArea(contours[i],false); 
    if(a>largest_area) 
    { 
    largest_area=a; 
    largest_contour_index=i; 
    } 
} 
Contour = Mat(ImageROI.size().width,ImageROI.size().height,CV_8UC1,Scalar::all(0)); 


drawContours(Contour, contours,largest_contour_index,Scalar(255),CV_FILLED, 8,hierarchy); 

vector<Point>hull; 

convexHull(contours[largest_contour_index],hull,CV_CLOCKWISE,true); 
drawContours(Contour, Mat(hull),largest_contour_index,Scalar(255),3, 8); 

namedWindow("Contour", WINDOW_NORMAL);    
imshow("Contour", Contour);      

OriginalImage.release(); 
BackgroundImage.release(); 
GrayImage.release(); 
Binary.release(); 
BinaryMorph.release(); 
ImageROI.release(); 
Contour.release(); 

waitKey(0);            
return 0;} 

我已經寫上面的代碼來繪製使用的OpenCV 2.4.9使用Microsoft Visual Studio 2010所明示的最大輪廓的凸包的最大輪廓的凸包。該代碼遵循並執行沒有任何錯誤,成功繪製最大輪廓,但無法顯示輪廓。拉絲使用的OpenCV C++

請注意,我使用C api到目前爲止,現在試圖轉換爲C++。所以,我對於使用openCV和C++來說是新的。你的意見,使程序工作繪製凸包將不勝感激。

回答

2

這裏的主要問題是你打電話drawContours錯誤地繪製凸包。

drawContours接受作爲輸入點的InputArrayOfArrays,即2維結構,而hull僅爲1維。

您可以輕鬆地解決這個動態創建的二維矢量,只有一個元素(hull),通過爲指標0,即二維結構的第一個元素剛創建:

vector<Point>hull; 
convexHull(contours[largest_contour_index], hull, CV_CLOCKWISE, true); 
drawContours(Contour, vector<vector<Point>> {hull}, 0, Scalar(128), 3, 8); 

,或者,如果C++ 11不可用:

vector<Point>hull; 
convexHull(contours[largest_contour_index], hull, CV_CLOCKWISE, true); 
vector<vector<Point>> tmp; 
tmp.push_back(hull); 
drawContours(Contour, tmp, 0, Scalar(128), 3, 8); 

而且,因爲你從一個C的背景下,一些提示是:

  • 在需要它們之前聲明變量,而不是在函數的開頭。
  • 您不需要手動發佈Mat s,因爲它們在超出範圍時會被其析構函數自動釋放。

另外:

  • ,如果你並不需要能夠調整窗口的大小,你不需要調用namedWindow因爲imshow只會創造你。 (在下面的代碼我放棄了所有的呼叫,namedWindow,但我無法改變他們了)
  • 既然你已經知道了你的矩陣(CV_8UC1)的類型,你可以使用Mat_<Tp>專業化,即Mat1b(又名Mat_<uchar>)。這將產生較少的詳細代碼,並且還允許您訪問像mat(i,j)這樣的元素,而不是mat.at<uchar>(i,j)(這裏不需要,但只是一般性的建議)。
  • dilate用空的內核是沒用的。請定義一個合適的內核。
  • 這裏你不需要hierarchy,所以不要使用它。
  • 使用更新的常量名:IMREAD_GRAYSCALE代替CV_LOAD_IMAGE_GRAYSCALECHAIN_APPROX_SIMPLE代替CV_CHAIN_APPROX_SIMPLE,等...
  • 最好不要放魔法值的代碼(如ROI值300,600)。
  • 如果您使用的是默認值,則不需要指定參數。
  • 大寫字母的名字通常用於類和結構名稱,而不是變量(這在某種程度上是主觀的,但我個人認爲它使代碼更易於閱讀)。
  • 如果您沒有檢測到任何輪廓,則跳過計算。
  • 如果您使用VisualStudio,而不是使用所有這些imshow進行調試,則可以使用Image Watch
  • 評論代碼!

這裏跟這些提示工作代碼適用於:

#include <opencv2/opencv.hpp> 
#include <vector> 
#include <string> 

using namespace std; 
using namespace cv; 

int main() 
{ 
    // Load images 
    Mat1b originalImage = imread("path_to_original_image", IMREAD_GRAYSCALE); 
    Mat1b backgroundImage = imread("path_to_bkg_image", IMREAD_GRAYSCALE); 

    // Create binary mask 
    Mat1b grayImage; 
    absdiff(originalImage, backgroundImage, grayImage); 
    Mat1b binary; 
    threshold(grayImage, binary, 80, 255, THRESH_BINARY); 

    imshow("OriginalImage", originalImage); 
    imshow("BackgroundImage", backgroundImage); 
    imshow("GrayImage", grayImage); 
    imshow("Binary", binary); 

    // Take a ROI 
    Rect roi(binary.cols/3, 0, (binary.cols * 2)/3, binary.rows); 
    Mat1b imageROI = binary(roi); 

    imshow("ImageROI", imageROI); 

    // Apply morphological dilate, 2 times 
    Mat1b binaryMorph; 
    Mat1b kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3)); 
    dilate(imageROI, binaryMorph, kernel, Point(-1, -1), 2); 

    imshow("BinaryMorph", binaryMorph); 

    // Find blob contours 
    vector<vector<Point>> contours; 
    double largest_area = 0.0; 
    int largest_contour_index = 0; 
    findContours(binaryMorph.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, roi.tl()); 

    if (!contours.empty()) 
    { 
     // Find largest contour 
     for (size_t i = 0; i < contours.size(); i++) 
     { 
      double a = contourArea(contours[i], false); 
      if (a > largest_area) 
      { 
       largest_area = a; 
       largest_contour_index = i; 
      } 
     } 

     // Draw largest contors 
     Mat3b contour(binary.rows, binary.cols, Vec3b(0, 0, 0)); 
     drawContours(contour, contours, largest_contour_index, Scalar(255, 255, 255), CV_FILLED); 

     // Find convex hull of largest contour 
     vector<Point>hull; 
     convexHull(contours[largest_contour_index], hull, CV_CLOCKWISE, true); 

     // Draw the convex hull 
     vector<vector<Point>> tmp; 
     tmp.push_back(hull); 
     drawContours(contour, tmp, 0, Scalar(0, 0, 255), 3); 

     imshow("Contour", contour); 
    } 

    waitKey(0); 
    return 0; 
} 
+0

非常感謝您的所有有用的提示!我很感激您的時間來修改我的代碼。但是,這個問題並沒有解決,因爲我在下面的代碼中得到了編譯錯誤:drawContours(contour,vector > {hull},0 .......它被加下劃線爲紅色並且表示,type名稱不允許在這裏,請幫助我 –

+0

你可能沒有啓用C++ 11,只需要:'vector > tmp; tmp.push_back(hull); drawContours(contour,tmp,0,Scalar 128),3);' – Miki

+0

你好,我提出了建議的改變,編譯錯誤消失了,但凸起不像以前那樣顯示,而且我想用紅色的凸面白色顯示輪廓,而這個背景是黑色的,請幫助我,我被困在這裏,因爲沒有顯示凸字 –