2015-03-17 4 views
1

Вот исходный код из MATLAB:OpenCV 2.4.10 bwlabel - связные компоненты

% Calculate each separated object area 
    cDist=regionprops(bwImg, 'Area'); 
    cDist=[cDist.Area]; 

    % Label each object 
    [bwImgLabeled, ~]=bwlabel(bwImg); 

    % Calculate min and max object size based on assumptions on the color 
    % checker size 
    maxLabelSize = prod(size(imageData)./[4 6]); 
    minLabelSize = prod(size(imageData)./[4 6]./10); 

    % Find label indices for objects that are too large or too small 
    remInd = find(cDist > maxLabelSize); 
    remInd = [remInd find(cDist < minLabelSize)]; 

    % Remove over/undersized objects 
    for n=1:length(remInd) 
     ri = bwImgLabeled == remInd(n); 
     bwImgLabeled(ri) = 0; 

Здесь используется мой код OpenCV

//regionprops(bwImg, 'Area'); 
// cDist=[cDist.Area] 
//cv::FileStorage file("C:\\Users\\gdarmon\\Desktop\\gili.txt", cv::FileStorage::WRITE); 
// 
//file << dst; 
dst.convertTo(dst,CV_8U); 
cv::vector<cv::vector<cv::Point> > contours; 
cv::vector<cv::Vec4i> hierarchy; 
cv::findContours(dst,contours,hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE); 

std::vector<cv::Moments> mu(contours.size()); 
for (int i = 0; i < contours.size(); i++) 
{ 
    mu[i] = cv::moments(contours[i],false); 
} 
vector<cv::Point2f> mc(contours.size()); 
for(int i = 0; i < contours.size(); i++) 
{ 
    mc[i] = cv::Point2f(mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00); 
} 

Поскольку в настоящее время Ihave контуров Я хотел бы пользователь bwlabel function
1. Я понял, что этикетирование сделано для подключения 4-8 объектов. не могли бы вы объяснить, что такое маркировка на самом деле? Я бы сделал ажиотаж любой ссылкой.
2. connected components in OpenCV В этой статье некоторые люди говорят о CVblob, а некоторые о cvContourArea от opecv, можете ли вы объяснить разницу. и что будет лучше подходит для моего случая использования?

Update: вот что я попытался с помощью cvBlobs

IplImage* img_bw = new IplImage(dst); 
CBlobResult blobs; 
CBlob *currentBlob; 
blobs = CBlobResult(img_bw, NULL, 0); 
// Exclude all white blobs smaller than the given value (80) 
// The bigger the last parameter, the bigger the blobs need 
// to be for inclusion 
blobs.Filter(blobs, 
    B_EXCLUDE, 
    CBlobGetArea(), 
    B_LESS, 
    80); 

// Get the number of blobs discovered 
int num_blobs = blobs.GetNumBlobs(); 

// Display the filtered blobs 
IplImage* filtered = cvCreateImage(cvGetSize(img_bw), 
    IPL_DEPTH_8U, 
    3); 

cvMerge(img_bw, img_bw, img_bw, NULL, filtered); 

for (int i = 0; i < num_blobs; i++) 
{ 
    currentBlob = blobs.GetBlob(i); 
    currentBlob->FillBlob(filtered, CV_RGB(255,0,0)); 
} 

// Display the input/output windows and images 
cvNamedWindow("input"); 
cvNamedWindow("output"); 
cvShowImage("input", img_bw); 

cvShowImage("output", filtered); 
cv::waitKey(0); 

/*% Calculate min and max object size based on assumptions on the color 
% checker size 
maxLabelSize = prod(size(imageData)./[4 6]); 
minLabelSize = prod(size(imageData)./[4 6]./10);*/ 
double maxLabelSize = (dst.rows/4.0) * (dst.cols/6.0); 
double minLabelSize = ((dst.rows/40.0) * (dst.cols/60.0)); 
+0

если вы голос близко пожалуйста, объясните почему. – Gilad

ответ

12
  1. я понял, что маркировка делается для того, чтобы подключиться 4-8 объектов. не могли бы вы объяснить, что такое маркировка на самом деле? Я бы сделал ажиотаж любой ссылкой.

Ярчайший демонстрация того, что на самом деле делает маркировка в документации Matlab для bwlabel. Если сравнить исходную матрицу BW к полученной матрице L, вы увидите, что он принимает двоичный файл и присваивает уникальные метки для каждой подключенной группы 1-х:

L = 

    1  1  1  0  0  0  0  0 
    1  1  1  0  2  2  0  0 
    1  1  1  0  2  2  0  0 
    1  1  1  0  0  0  3  0 
    1  1  1  0  0  0  3  0 
    1  1  1  0  0  0  3  0 
    1  1  1  0  0  3  3  0 
    1  1  1  0  0  0  0  0 

Здесь есть три компонента меченый. В этом примере рассматриваются 4-связанные компоненты; считается, что пиксель подключен к текущему пикселю, если он находится слева, справа, над или под ним. 8-подключенные объекты включают диагонали, которые приведут к тому, что метки 2 и 3 будут объединены для матрицы выше, поскольку нижний правый угол объекта 2 и верхняя часть объекта 3 диагонально соединены. Алгоритм маркировки подключенных компонентов описан в Википедии here.

2.соединенные компоненты в OpenCV в этой статье некоторые люди говорят о CVblob, а некоторые о cvContourArea от opecv, можете ли вы объяснить разницу. и что будет лучше подходит для моего случая использования?

OpenCV 3.0 из бета-версии и имеет два совершенно новых методов: connectedComponents и connectedComponentsWithStats (documentation). Если вы пытаетесь воспроизвести Matlab's bwlabel, это путь.

Я написал тестовую программу, чтобы попробовать connectedComponentsWithStats (полный код ниже), используя это как мой тест изображение:

Original Image

(На самом деле, это изображение уменьшается от 800х600 до 400x300, но код генерировать он включен ниже.)

я произвел меченого изображение с помощью:

int nLabels = connectedComponentsWithStats(src, labels, stats, centroids, 8, CV_32S); 

Значение, возвращенное в nLabels является 5. Помните, что этот метод считает фон ярлыком 0.

Чтобы узнать, что обозначены областями, вы можете масштабировать значения оттенков серого от [0..nLabels-1] до [0..255], или вы можете назначить случайные значения RGB и создать цветное изображение. Для этого теста я просто распечатал значения в нескольких местах, которые, как я знал, были в разных компонентах.

cout << "Show label values:" << endl; 
// Middle of square at top-left 
int component1Pixel = labels.at<int>(150,150); 
cout << "pixel at(150,150) = " << component1Pixel << endl; 
// Middle of rectangle at far right 
int component2Pixel = labels.at<int>(300,550); 
cout << "pixel at(300,550) = " << component2Pixel << endl << endl; 

Show label values: 
pixel at(150,150) = 1 
pixel at(300,550) = 2 

stats является 5 x nLabels матом, содержащим left, top, width, height, and area для каждого компонента (в том числе фона). Для этого изображения:

stats: 
(left,top,width,height,area) 
[0, 0, 800, 600, 421697; 
100, 100, 101, 101, 10201; 
500, 150, 101, 301, 30401; 
350, 246, 10, 10, 36; 
225, 325, 151, 151, 17665] 

Вы заметите, что компонент 0 является полная ширина/высота изображения. Суммируя все области, вы получаете 480,000 = 800x600. Первые 4 элемента могут быть использованы для создания ограничивающего прямоугольника:

Rect(Point(left,top), Size(width,height)) 

centroids является 2 x nLabels Mat, содержащий x, y координаты центроида каждого компонента:

centroids: 
(x, y) 
[398.8575636060963, 298.8746232484461; 
150, 150; 
550, 300; 
354.5, 250.5; 
300, 400] 

Наконец, в какой-то момент» вероятно, захочет сделать дальнейшую обработку на одном из компонентов по отдельности. Здесь я использую compare для создания нового Mat only2, который содержит только пиксели от labels, которые помечены как 2.

compare(labels, 2, only2, CMP_EQ); 

compare услужливо устанавливает эти пиксели на значение 255 в новом изображении, так что вы можете увидеть результаты:

Only Component 2

Вот полный код:

#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/imgcodecs.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include <iostream> 

using namespace std; 
using namespace cv; 

int main(int argc, const char * argv[]) { 

    // Create an image 
    const int color_white = 255; 
    Mat src = Mat::zeros(600, 800, CV_8UC1); 

    rectangle(src, Point(100, 100), Point(200, 200), color_white, CV_FILLED); 
    rectangle(src, Point(500, 150), Point(600, 450), color_white, CV_FILLED); 
    rectangle(src, Point(350,250), Point(359,251), color_white, CV_FILLED); 
    rectangle(src, Point(354,246), Point(355,255), color_white, CV_FILLED); 
    circle(src, Point(300, 400), 75, color_white, CV_FILLED); 

    imshow("Original", src); 

    // Get connected components and stats 
    const int connectivity_8 = 8; 
    Mat labels, stats, centroids; 

    int nLabels = connectedComponentsWithStats(src, labels, stats, centroids, connectivity_8, CV_32S); 

    cout << "Number of connected components = " << nLabels << endl << endl; 

    cout << "Show label values:" << endl; 
    int component1Pixel = labels.at<int>(150,150); 
    cout << "pixel at(150,150) = " << component1Pixel << endl; 
    int component2Pixel = labels.at<int>(300,550); 
    cout << "pixel at(300,550) = " << component2Pixel << endl << endl; 

    // Statistics 
    cout << "Show statistics and centroids:" << endl; 
    cout << "stats:" << endl << "(left,top,width,height,area)" << endl << stats << endl << endl; 
    cout << "centroids:" << endl << "(x, y)" << endl << centroids << endl << endl; 

    // Print individual stats for component 1 (component 0 is background) 
    cout << "Component 1 stats:" << endl; 
    cout << "CC_STAT_LEFT = " << stats.at<int>(1,CC_STAT_LEFT) << endl; 
    cout << "CC_STAT_TOP = " << stats.at<int>(1,CC_STAT_TOP) << endl; 
    cout << "CC_STAT_WIDTH = " << stats.at<int>(1,CC_STAT_WIDTH) << endl; 
    cout << "CC_STAT_HEIGHT = " << stats.at<int>(1,CC_STAT_HEIGHT) << endl; 
    cout << "CC_STAT_AREA = " << stats.at<int>(1,CC_STAT_AREA) << endl; 

    // Create image with only component 2 
    Mat only2; 
    compare(labels, 2, only2, CMP_EQ); 

    imshow("Component 2", only2); 

    waitKey(0); 

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