OpenCV を使用してバイナリ イメージ内の最大のブロブの境界ボックスを見つける最も効率的な方法は何ですか? 残念ながら、OpenCV にはブロブ検出のための特定の機能がありません。リスト内の最大のものを使用findContours()
して検索する必要がありますか?
5 に答える
ここ。これ。は。(参考: 怠惰にならないようにして、以下の関数で何が起こるかを理解してください。
cv::Mat findBiggestBlob(cv::Mat & matImage){
int largest_area=0;
int largest_contour_index=0;
vector< vector<Point> > contours; // Vector for storing contour
vector<Vec4i> hierarchy;
findContours( matImage, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
for( int i = 0; i< contours.size(); i++ ) {// iterate through each contour.
double a=contourArea( contours[i],false); // Find the area of contour
if(a>largest_area){
largest_area=a;
largest_contour_index=i; //Store the index of largest contour
//bounding_rect=boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
}
}
drawContours( matImage, contours, largest_contour_index, Scalar(255), CV_FILLED, 8, hierarchy ); // Draw the largest contour using previously stored index.
return matImage;
}
OpenCV ライブラリを使用する場合は、OpenCVs SimpleBlobDetector を確認してください。これは、その小さなチュートリアルを示す別のスタック オーバーフローです: OpenCV SimpleBlobDetector の使用方法
ただし、これは重要なポイントのみを提供します。これを最初の検索として使用して、必要なブロブを見つけてから、可能性が最も高いブロブの周りで findContours アルゴリズムを使用できます。
また、BLOB について知っている情報が多ければ多いほど、不要な BLOB を除外するパラメーターを指定できます。SimpleBlobDetector の面積パラメーターをテストすることをお勧めします。おそらく、画像の領域のサイズに基づいて領域を計算し、アルゴリズムがブロブを検出しない場合は、より小さなブロブを繰り返し許可することができます。
メインのOpenCVドキュメントへのリンクは次のとおりです。
誰も完全な OpenCV ソリューションを投稿していないため、しきい値処理 + 輪郭領域フィルタリングを使用した簡単なアプローチを次に示します。
入力画像
緑色で強調表示された最大のブロブ/輪郭
import cv2
# Load image, grayscale, Gaussian blur, and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Find contours and sort using contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
# Highlight largest contour
cv2.drawContours(image, [c], -1, (36,255,12), 3)
break
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()
TimZaman、あなたのコードにはバグがありますが、コメントできないので、新しい正しい答えを始めます。1" と TimZaman のアイデアに基づく私のソリューションは次のとおりです。
Mat measure::findBiggestBlob(cv::Mat &src){
int largest_area=0;
int largest_contour_index=0;
Mat temp(src.rows,src.cols,CV_8UC1);
Mat dst(src.rows,src.cols,CV_8UC1,Scalar::all(0));
src.copyTo(temp);
vector<vector<Point>> contours; // storing contour
vector<Vec4i> hierarchy;
findContours( temp, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
for( int i = 0; i< contours.size(); i++ ) // iterate
{
double a=contourArea( contours[i],false); //Find the largest area of contour
if(a>largest_area)
{
largest_area=a;
largest_contour_index=i;
}
}
drawContours( dst, contours,largest_contour_index, Scalar(255), CV_FILLED, 8, hierarchy );
// Draw the largest contour
return dst;
}