2017-02-09 15 views
1

OpenCVで平均2つのブロブを作成しようとしています。私は次のように前処理画像上流域アルゴリズムを使用することを計画していたことを達成するために:結果と流域の境界が1つの領域を密接に囲んでいる

cv::Mat common, diff, processed, result; 
cv::bitwise_and(blob1, blob2, common); //calc common area of the two blobs 
cv::absdiff(blob1, blob2, diff);  //calc area where they differ 

cv::distanceTransform(diff, processed, CV_DIST_L2, 3); //idea here is that the highest intensity 
                 //will be in the middle of the differing area 
cv::normalize(processed, processed, 0, 255, cv::NORM_MINMAX, CV_8U); //convert floats to bytes 

cv::Mat watershedMarkers, watershedOutline; 
common.convertTo(watershedMarkers, CV_32S, 1./255, 1); //change background to label 1, common area to label 2 
watershedMarkers.setTo(0, processed); //set 0 (unknown) for area where blobs differ 

cv::cvtColor(processed, processed, CV_GRAY2RGB); //watershed wants 3 channels 
cv::watershed(processed, watershedMarkers); 
cv::rectangle(watershedMarkers, cv::Rect(0, 0, watershedMarkers.cols, watershedMarkers.rows), 1); //remove the outline 

//draw the boundary in red (for debugging) 
watershedMarkers.convertTo(watershedOutline, CV_16S); 
cv::threshold(watershedOutline, watershedOutline, 0, 255, CV_THRESH_BINARY_INV); 
watershedOutline.convertTo(watershedOutline, CV_8U); 
processed.setTo(cv::Scalar(CV_RGB(255, 0, 0)), watershedOutline); 

//convert computed labels back to mask (blob), less relevant but shows my ultimate goal 
watershedMarkers.convertTo(watershedMarkers, CV_8U); 
cv::threshold(watershedMarkers, watershedMarkers, 1, 0, CV_THRESH_TOZERO_INV); 
cv::bitwise_not(watershedMarkers * 255, result); 

私の問題は、計算された境界が(ほぼ)常に両方の塊に共通領域に隣接しているということです。赤色で描画結果の概要と(灰色黒= 0、= 1、白= 2)

入力マーカー Input markers

流域入力画像(距離変換結果): watershed input image with drawn outline

ここピクチャであります

私は境界線が入力の最大強度領域に沿って(すなわち、異なる領域の中央に沿って)行くと予想します。代わりに(あなたが見ることができるように)、それは主に2とマークされた領域の周りを行き来し、背景に触れるようにビットがシフトされます(1とマークされます)。私はここで何か間違っているのですか、あるいは流域の仕組みを誤解しましたか?

+0

参照[THIS](http://stackoverflow.com/questions/31961240/opencv-watershed-segmentation-miss-some-objects?rq=1) –

+0

@JeruLukeのおかげで、しかし、それではありません。私の背景はラベル1とオブジェクト2を持っています。 – slawekwin

+0

距離の変換を逆にすると、より遠くにあるポイントの値が小さくなります。 'processed = 255 - processed;を' normalize'行の後に追加します。 – Miki

答えて

1

このイメージ最低料金:

enter image description here

あなたは単に流域アルゴリズムにすべてゼロ画像を渡して、正しい結果を得ることができます。

enter image description here「流域」は、その後均等各「側」(そしてちょうど分水嶺アルゴリズムによって-1にデフォルトで設定されている外側の境界線を除去するために覚えている)から出発「水」で充填されています

コード:

#include <opencv2\opencv.hpp> 

using namespace cv; 
using namespace std; 

int main() 
{ 
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE); 

    Mat1i markers(img.rows, img.cols, int(0)); 
    markers.setTo(1, img == 128); 
    markers.setTo(2, img == 255); 

    Mat3b image(markers.rows, markers.cols, Vec3b(0,0,0)); 
    markers.convertTo(markers, CV_32S); 
    watershed(image, markers); 

    Mat3b result; 
    cvtColor(img, result, COLOR_GRAY2BGR); 
    result.setTo(Scalar(0, 0, 255), markers == -1); 

    imshow("Result", result); 
    waitKey(); 

    return(0); 
} 
関連する問題