Блоб (Binary Large OBject — blob) представляет собой скопление связанных пикселов изображения. Существует библиотека cvBlobsLib, которая предоставляет функции для работы с блобами.
Попробуем применить её в связке с Qt. Для этого скачаем последнюю актуальную версию для Linux (даже если вы работаете в системе windows), скомпилируем статическую библиотеку. Для этого добавим в профайл
CONFIG += staticlib
и добавив следующие подключения (возможно есть лишние, позже отредактирую)
INCLUDEPATH += D:\\dev\\opencv\\include
INCLUDEPATH += D:\\dev\opencv\\include\\opencv
INCLUDEPATH += D:\\dev\opencv\\mingw32\\install\\include
INCLUDEPATH += D:\\dev\\opencv\\build\\x64\\mingw\\bin
INCLUDEPATH += D:\\cvblobs8.3_linux
LIBS += D:\\opencv\\libopencv_core231.dll
LIBS += D:\\opencv\\libopencv_highgui231.dll
LIBS += D:\\opencv\\libopencv_imgproc231.dll
LIBS += D:\\opencv\\libopencv_flann231.dll
LIBS += D:\\opencv\\libopencv_features2d231.dll
LIBS += D:\\opencv\\libopencv_calib3d231.dll
LIBS += D:\\opencv\\libopencv_video231.dll
LIBS += D:\\opencv\\libopencv_legacy231.dll
LIBS += D:\\opencv\\libopencv_ml231.dll
LIBS += D:\\opencv\\libopencv_objdetect231.dll
LIBS += D:\\opencv\\libopencv_contrib231.dll
После компиляции получим файл с расширением .a (название зависит от название проекта). Для удобства скопируем библиотеку в отдельную папку, например, в D:\libs.
Теперь рассмотрим examples-пример. Создадим новый консольный проект и не забудем добавить LIBS += D:\\libs\\libblobsLib.a.
#include <QtCore/QCoreApplication>
#include<QDebug>
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include <stdio.h>
#include "BlobResult.h"
char wndname[] = "Blob Extraction";
char tbarname1[] = "Threshold";
char tbarname2[] = "Blob Size";
// The output and temporary images
IplImage* originalThr = 0;
IplImage* original = 0;
IplImage* displayedImage = 0;
int param1,param2;
CvFont font;
//initilize font
void init_font()
{
cvInitFont(&font, CV_FONT_NORMAL,0.5,0.5,0,1,8);
}
// threshold trackbar callback
void on_trackbar( int dummy )
{
if(!originalThr)
{
originalThr = cvCreateImage(cvGetSize(original), IPL_DEPTH_8U,1);
}
if(!displayedImage)
{
displayedImage = cvCreateImage(cvGetSize(original), IPL_DEPTH_8U,3);
}
// gaussianBlur
cvSmooth(original, originalThr, CV_GAUSSIAN, 5, 5);
// threshold input image
cvThreshold( originalThr, originalThr, param1, 255, CV_THRESH_BINARY);
// get blobs and filter them using its area
CBlobResult blobs;
int i;
CBlob *currentBlob;
// find blobs in image blobs = CBlobResult( originalThr, NULL, 0 ); blobs.Filter( blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, param2 ); // display filtered blobs cvMerge( originalThr, originalThr, originalThr, NULL, displayedImage ); for (i = 0; i < blobs.GetNumBlobs(); i++ ) { currentBlob = blobs.GetBlob(i); double xc=(currentBlob->Moment(1,0)/currentBlob->Moment(0,0)); double yc=(currentBlob->Moment(0,1)/currentBlob->Moment(0,0)); double equation =currentBlob->Area()/currentBlob->Perimeter(); currentBlob->FillBlob( displayedImage, CV_RGB(100,0,0)); cvCircle( displayedImage, cvPoint(xc,yc),3, CV_RGB(0,255,255), -1, 8, 0 ); cvPutText(displayedImage,QString::number(equation ,'f',2).toStdString().c_str(), cvPoint(xc,yc),&font, CV_RGB(255,255,0)); } cvShowImage( wndname, displayedImage ); } void update_view() { for(;;) { int c; on_trackbar(0); c = cvWaitKey(0); if( c == 27 ) break; } } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); param1 = 30; param2 = 20; init_font(); QString dirPath=QCoreApplication::applicationDirPath(); dirPath.replace("/","\\"); original = cvLoadImage(QString(dirPath+"\\image.bmp").toStdString().c_str(),0); cvNamedWindow(wndname, CV_WINDOW_AUTOSIZE); cvCreateTrackbar( tbarname1, wndname, ¶m1, 255, on_trackbar ); cvCreateTrackbar( tbarname2, wndname, ¶m2, 100, on_trackbar ); update_view();// Call to update the view cvReleaseImage( &original ); cvReleaseImage( &originalThr ); cvReleaseImage( &displayedImage ); cvDestroyWindow( wndname ); a.exec(); }Данный пример демонстрирует работу с блобами. Для изображения image.bmp, находящегося в папке .exe программы, выделяет объекты (в зависимости от значений порога бинаризации и минимального размера блоба в пикелях) и для блобов, отвечающих параметрам порога и минимального размера, отмечает отношение площади к периметру.
![]() |
Результат работы программы |
Если есть вопросы с удовольствием на них отвечу.