c++ openCV 2.4.10 bwlabel-कनेक्टेड घटक



matlab image-processing (1)

  1. मैंने सोचा है कि लेबलिंग 4-8 ऑब्जेक्ट्स कनेक्ट करने के लिए किया गया है। क्या आप कृपया बता सकते हैं कि वास्तव में लेबलिंग क्या है? मैं किसी लिंक को एपीरियस कर दूंगा

वास्तव में क्या लेबलिंग का स्पष्ट प्रदर्शन bwlabel लिए bwlabel प्रलेखन में है। यदि आप परिणामी मैट्रिक्स L में मूल मैट्रिक्स BW तुलना करते हैं, तो आप देखेंगे कि यह एक द्विआधारी छवि लेता है और 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 के शीर्ष पर तिरंगा जुड़े होते हैं। जुड़े घटक लेबलिंग एल्गोरिथम को विकिपीडिया पर वर्णित किया गया है

2. इस लेख में ओपनसीवी में कनेक्टेड घटकों में कुछ लोग सीवीब्लॉब के बारे में बात कर रहे हैं और कुछ ओपेकव के सीवीसीटोरएरिया के बारे में बात कर रहे हैं, क्या आप अंतर की व्याख्या कर सकते हैं? और मेरे उपयोग के मामले के लिए बेहतर क्या होगा?

ओपनसीवी 3.0 बीटा से बाहर है और इसके दो नए तरीके हैं: connectedComponents और connectedComponentsWithStats ( प्रलेखन )। अगर आप bwlabel के bwlabel को दोहराने की कोशिश कर रहे हैं, तो यह जाने का तरीका है।

मैंने अपनी परीक्षण छवि के रूप में इसे प्रयोग करने के लिए connectedComponentsWithStats करने के लिए एक परीक्षण कार्यक्रम लिखा था।

(वास्तव में, यह छवि 800x600 से 400x300 तक कम हो जाती है, लेकिन इसे उत्पन्न करने के लिए कोड नीचे शामिल है।)

मैंने लेबलयुक्त छवि का उपयोग करके उत्पन्न किया है:

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

nLabels में लौटाया जाने nLabels मूल्य 5 याद रखें, कि यह विधि पृष्ठभूमि को लेबल 0 मानता है।

यह देखने के लिए कि लेबल वाले क्षेत्र क्या हैं, आप [0..nLabels-1] से [0..255] तक ग्रेस्केल मान [0..255] सकते हैं, या आप यादृच्छिक आरजीबी मूल्यों को असाइन कर सकते हैं और एक रंग छवि बना सकते हैं। इस परीक्षा के लिए मैंने कुछ स्थानों पर मूल्यों को मुद्रित किया जो मुझे पता था अलग-अलग घटकों में।

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 करते हुए, आपको 480,000 = 800x600 मिलता है। पहले 4 तत्वों का उपयोग एक सीमा आयताकार बनाने के लिए किया जा सकता है:

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

centroids एक 2 x nLabels चटाई है जिसमें x, y के प्रत्येक घटक के केंद्र के x, y निर्देशांक शामिल हैं:

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

अंत में, कुछ बिंदु पर आप संभवत: एक घटकों पर अलग-अलग प्रसंस्करण करना चाहते हैं। यहाँ मैं एक नया Mat केवल 2 उत्पन्न करने के लिए compare करता only2 जिसमें केवल 2 लेबल वाले labels पिक्सेल शामिल होते हैं

compare(labels, 2, only2, CMP_EQ);

ये पिक्सल को नई छवि में 255 मान के साथ मदद से compare ताकि आप परिणाम देख सकें:

यहां पूरा कोड है:

#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);

}

यहां मैटलैब से मूल कोड है:

 % 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;

ओपनसीवी का उपयोग करके मेरा कोड यहां है I

//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 ); 
}

चूंकि अब आकृतियाँ आ गई हैं, मैं उपयोगकर्ता के लिए bwlabel फ़ंक्शन चाहूंगा
1. मैंने सोचा है कि लेबलिंग 4-8 ऑब्जेक्ट्स को जोडने के लिए किया जाता है। क्या आप कृपया बता सकते हैं कि वास्तव में लेबलिंग क्या है? मैं किसी लिंक को एपीरियस कर दूंगा
2. इस लेख में ओपनसीवी में कनेक्टेड घटकों में कुछ लोग सीवीब्लॉब के बारे में बात कर रहे हैं और कुछ ओपेकव के सीवीसीटोरएरिया के बारे में बात कर रहे हैं, क्या आप अंतर की व्याख्या कर सकते हैं और मेरे उपयोग के मामले के लिए बेहतर क्या होगा?

अद्यतन: यहाँ मैं 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));




opencv-contour