2017-07-05 15 views
-1

私は次の画像を持っています Candies そして私はすべてのキャンディーを数えようとしますが、それらのいくつかは交差します。私の次のコードは動作しません。以下のコードは、交差しない場合にのみキャンディーを識別することができます。しかし、交差するとどうするか考えてもいません。opencvですべてのキャンディを検出して数える方法

int main(int argc, char** argv) 
{ 
Mat src = imread("C:\\data\\Assignment1A.jpg",0); // reads image from file 
Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3); 

cv::Scalar min(245, 0, 0); 
cv::Scalar max(255, 255, 255); 
cv::inRange(src, min, max, dst); 

namedWindow("Source", 1); 
imshow("Source", dst); 

vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 

findContours(dst, contours, hierarchy, 
    CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); 

cout <<contours.size(); 
size_t count = contours.size(); 
int i = 0; 
for(size_t i = 0; i < contours.size(); i++) { 
    cv::Point2f c; 
    float r; 
    cv::minEnclosingCircle(contours[i], c, r); 
    if (r > 10) { 
     i++;  } 
} 

cout << i << " candies"; 
waitKey(0); 
return 0; 
} 

誰でもこの問題の解決方法を教えてもらえますか?

+0

を_ "私の次のコードは動作しません" _有効な問題の記述ではありません。 [ヘルプセンター](http://stackoverflow.com/help)にアクセスし、[よく質問する方法]セクション(http://stackoverflow.com/help/how-to-ask)を読んでください。 –

+0

上記のコードは、交差しない場合にのみキャンディーを識別することができます。しかし、私は彼らが交差する場合に何をすべきかについての考えを持っていません。 –

+0

輪郭のような中間画像(描画輪郭を使用して)、minEnclosingCircleの結果などを投稿してください。 –

答えて

0

これはおそらく非常に良い解決策ではありません(同じ色のキャンディーが重ならないという前提でのみ動作します)。 (this article変換し、流域の距離を使用する方法についてもありますが、私は多分キャンディーはあまり重なって、それがこのためにフォーク作ることができなかった?)

  1. それはノイズをたくさん持っているし、特にので(白色の背景を削除しますJPEGアーティファクト)。

enter image description here

  • HSVに変換してHチャネルを取る(コメントで示唆したように)。 ソートは、3つの値(色相)を3つではなく(赤、緑、青)の色を表しており、これらのすべての表面の不規則性をある程度無視しているため、ここでは便利です。下の楕円の一部を背景と区別することはできませんが、心配する必要はありません。
  • enter image description here

    Hの狭い範囲について
  • (例えば、[1、20])、(それらの領域の点で)十分に大きな輪郭を見つけるすることが1つのキャンディですが、1つのキャンディ以上にはならないほど小さいです。範囲の[21,40]、[41,60]などでHを繰り返すと、179の最高の色相値に達するまで表示されます。輪郭はそれほど良好ではありませんが、カウントには十分です。あなたは、必要に応じて、迷惑を取り除くために、すべてのステップで拡張/侵食を行うことで、おそらくそれらを改善することができます。

    enter image description here

    Pythonコード

  • は、それがどのように動作するかを示すために:

    import cv2 
    import numpy as np 
    
    #get only contours of more or less the single candy size 
    #noise is not included because its area is too small 
    #overlapping candies are not included because their area is too big 
    #probably there are smarter ways (area/circumference ratio, ellipse fitting, etc.) 
    def get_contours(img): 
        area_threshold_max = 120*120 #nice hard-coded empirical values 
        area_threshold_min = 50*50 
    
        _, contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 
        areas = [cv2.contourArea(c) for c in contours] 
        contours = [c for n, c in enumerate(contours) if area_threshold_min < areas[n] < area_threshold_max] 
        return contours 
    
    #remove background 
    img_g = cv2.imread("candy.jpg", 0) #read as grayscale 
    _, thresh = cv2.threshold(img_g, 235, 1, cv2.THRESH_BINARY_INV) #mask to include everything that isn't too white 
    img = cv2.imread("candy.jpg") #read again as a color image 
    black = np.zeros(img.shape).astype(img.dtype) #black image to combine with 
    img = cv2.bitwise_or(img, black, mask = thresh) 
    
    #convert to HSV and take only the H value 
    img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)[:, :, 0] 
    
    #find contours of a more or less appropriate size within a narrow H range, 
    #remove them from the image, increment H, repeat 
    contours_all = [] 
    h_step = 20 
    for h_start in range(0, 180, h_step): 
        rng = np.zeros(img.shape).astype(np.uint8) 
        rng = cv2.inRange(img, h_start + 1, h_start + h_step) 
        contours = get_contours(rng) 
        contours_all += contours 
    
    #draw our contours with their numbers on top of the original image 
    img_to_draw = cv2.imread("candy.jpg") 
    cv2.drawContours(img_to_draw, contours_all, -1, (0, 0, 0), 2) 
    for i, cnt in enumerate(contours_all): 
        (x, y), radius = cv2.minEnclosingCircle(cnt) 
        cv2.putText(img_to_draw, "%d" % (i + 1), (int(x-20), int(y+10)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 3) 
    cv2.putText(img_to_draw, "%d candies" % len(contours_all), (5, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 3) 
    cv2.imwrite("result2.png", img_to_draw) 
    
    関連する問題