2011-11-17 70 views
3

我们正在编写一个程序,它接收来自网络摄像机的输入,除绿色值以外的所有颜色,找到分离的BLOB并对它们进行编码。最终,这将被用作视频游戏的输入,但现在这是无关紧要的。FindContours如何在图像中循环? OpenCV 2.3

有问题的代码不是实际执行所有这些操作的代码,而是代码的重写段,以测试FindContours的实际工作方式。 通常,在图像处理方面,我们一直认为图像是从左上角向右下角读取的,但经过一些测试后,它看起来完全相反,从右下角开始并移动到左上角!

所以这里的问题是:FindContours以什么顺序发现它是轮廓?我的想法是对的还是我自己的代码让我困惑?

输入:Blobtest06

"Components" window

Console

#include <opencv2/opencv.hpp> 
#include <iostream> 
#include <opencv2/core/mat.hpp> 
#include <Windows.h> //for sleep function 

using namespace cv; 
using namespace std; 

void IsolateGreen(Mat mIn, Mat& mOut) 
{ 
Mat inImg (mIn.rows, mIn.cols, CV_8UC3, Scalar(1,2,3)); 
inImg.data = mIn.data; 
Mat channelRed (inImg.rows, inImg.cols, CV_8UC1); 
Mat channelGreen (inImg.rows, inImg.cols, CV_8UC1); 
Mat channelBlue (inImg.rows, inImg.cols, CV_8UC1); 
Mat outImg[] = {channelRed, channelGreen, channelBlue}; 

int fromTo[] = { 0,2, 1,1, 2,0}; 
mixChannels(&inImg, 1, outImg, 3, fromTo, 3); 

mOut = (channelGreen) - (channelRed + channelBlue); 

threshold(mOut, mOut, 5, 255, THRESH_BINARY); 

erode(mOut, mOut, Mat(), Point (-1,-1), 1); 
dilate(mOut, mOut, Mat(), Point(-1,-1), 2); 

} 

void FindContours(Mat& mDst, Mat mGreenScale, vector<vector<Point>>& vecContours, vector<Vec4i>& vecHierarchy, Mat img) 
{ 
//This is empty at all times. We need it to avoid crashes. 
vector<Vec4i> vecHierarchy2; 

// mGreenScale = mGreenScale > 1; //// MIGHT be entirely unneeded 

mDst = img > 1; 
findContours(mGreenScale, vecContours, vecHierarchy, 
     CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); 

/* Colors, in order: 
1st. = Red 
2nd. = Dark red 
3rd. = Purple 
4th. = Blue 
5th. = Baby blue 
6th. = Green 
7th. = Olive green 
8th. = Dark green 
*/ 

int aRed[] = {255, 100, 128, 0, 191, 0, 202, 0}; 
int aGreen[] = {0, 0, 0, 0, 239, 255, 255, 100}; 
int aBlue[] = {0, 0, 128, 255, 255, 0, 112, 0}; 
string sColor[] = {"Red", "Dark red", "Purple", "Blue", "Baby blue", "Green", "Light green", "Dark green"}; 

//its important that we check if there is anything in vecHierarchy (else) {crash} :P 
//function drawContours cannot handle an empty vedHierarchy 
if (vecHierarchy != vecHierarchy2) 
{ 
    // iterate through all the top-level contours, 
    for(int idx = 0; idx >= 0; idx = vecHierarchy[idx][0]) 
    { 
     // draw each connected component with its own FIXED color 
     Scalar color(aBlue[idx], aGreen[idx], aRed[idx]); 
     drawContours(mDst, vecContours, idx, color, /*1*/ CV_FILLED, 8, vecHierarchy); 
     cout << vecContours[idx][0] << " - - " << sColor[idx] << " - - Index: " << idx << endl; 
    } 
} 
cout << "Objects: "; 
cout << vecContours.size(); 
cout << endl; 

} 




int main() 
    { 
    Mat img = imread("Blobtest06.png"); 
    Mat mGreenScale; 

    //These next 5 instances ties to contourfinding     
    cvtColor(img, mGreenScale, CV_8UC3); //sets the right rows and cols 
    vector<vector<Point>> vecContours; //points to each pixel in a contour 
    vector<Vec4i> vecHierarchy; //A hierarchy for the functions 
    Mat mDst = Mat::zeros(mGreenScale.rows, mGreenScale.cols, CV_8UC3); //mDst image 


    IsolateGreen(img, mGreenScale); 
    FindContours(mDst, mGreenScale, vecContours, vecHierarchy, img); 

    namedWindow("Components", 1); 
    imshow("Components", mDst); 
    namedWindow("Source", 1); 
    imshow("Source", mGreenScale); 

    waitKey(); 
    return 0; 
    } 

PS:对不起,可怕的语法。该网站很困难,只是午餐时间。

回答

5

如果您关心OpenCV(开源库)的实现细节,您可以随时致电download the source并自行阅读。

警告:C++ API在某些事情上使用C API,包括FindCountours()。所以,如果你检查文件:modules/imgproc/src/contours.cpp线你会看到C++实现这一功能的:

1472 void cv::findContours(InputOutputArray _image, OutputArrayOfArrays _contours, 
1473     OutputArray _hierarchy, int mode, int method, Point offset) 
1474 { 
1475  Mat image = _image.getMat(); 
1476  MemStorage storage(cvCreateMemStorage()); 
1477  CvMat _cimage = image; 
1478  CvSeq* _ccontours = 0; 
1479  if(_hierarchy.needed()) 
1480   _hierarchy.clear(); 
1481  cvFindContours(&_cimage, storage, &_ccontours, sizeof(CvContour), mode, method, offset); 
1482  if(!_ccontours) 
1483  { 
1484   _contours.clear(); 
1485   return; 
1486  } 

调用cvFindContours(),这是从C API,在这同一个文件中定义的上线 。

扫描过程本身上cvFindNextContour()描述,在线位于:

793 CvSeq * 
794 cvFindNextContour(CvContourScanner scanner) 
795 { 

,你可以清楚地看到:

824  for(; y < height; y++, img += step) 
825  { 
826   for(; x < width; x++) 
827   { 
+0

感谢您的回答 - 但!我似乎无法完全理解答案。我可以看到数学的工作方式,但它并没有给出任何洞察方向。它从哪个像素开始,它在哪里结束?我是一个初学者,在旁注中,所以请忍受我。 :) –