8

手のレントゲン写真があります。骨を自動的に抽出する必要があります。さまざまなテクニックを使って手を簡単に分割できます。しかし、私は骨を手に入れる必要があり、それらのテクニックを使用しても役に立ちません。一部の骨は他の骨よりも明るいため、しきい値処理を使用すると、そのうちのいくつかが消え、他の骨はしきい値の上昇がより明確になります。そして、手の領域のみを閾値化する必要があると思いますか? 正方形ではない ROI のしきい値を設定することはできますか? O多分あなたは他の解決策、アドバイスを持っていますか? たぶん、OpenCV などのライブラリがいくつかあるのでしょうか。どんな助けでも非常に素晴らしいでしょう!

拡張:

生画像 期待される出力

                 Raw 画像の                      期待される出力

4

1 に答える 1

10

1 つのアプローチは、画像から手と指をセグメント化することです。

ここに画像の説明を入力

そして、手のシルエットだけで別の画像を作成します。

ここに画像の説明を入力

シルエットができたら、イメージを浸食して少し小さくします。これは、手と指のイメージから手を差し引くために使用され、結果として指になります。

ここに画像の説明を入力

以下のコードは、このアプローチを実行する方法を示しています。

void detect_hand_and_fingers(cv::Mat& src);
void detect_hand_silhoutte(cv::Mat& src);

int main(int argc, char* argv[])
{
    cv::Mat img = cv::imread(argv[1]);
    if (img.empty())
    {
        std::cout << "!!! imread() failed to open target image" << std::endl;
        return -1;        
    }

    // Convert RGB Mat to GRAY
    cv::Mat gray;
    cv::cvtColor(img, gray, CV_BGR2GRAY);
    cv::Mat gray_silhouette = gray.clone();

    /* Isolate Hand + Fingers */

    detect_hand_and_fingers(gray);
    cv::imshow("Hand+Fingers", gray);
    cv::imwrite("hand_fingers.png", gray);

    /* Isolate Hand Sillhoute and subtract it from the other image (Hand+Fingers) */

    detect_hand_silhoutte(gray_silhouette);
    cv::imshow("Hand", gray_silhouette);
    cv::imwrite("hand_silhoutte.png", gray_silhouette);

    /* Subtract Hand Silhoutte from Hand+Fingers so we get only Fingers */

    cv::Mat fingers =  gray - gray_silhouette;
    cv::imshow("Fingers", fingers);
    cv::imwrite("fingers_only.png", fingers);
    cv::waitKey(0);

    return 0;
}

void detect_hand_and_fingers(cv::Mat& src)
{        
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3,3), cv::Point(1,1));
    cv::morphologyEx(src, src, cv::MORPH_ELLIPSE, kernel);    

    int adaptiveMethod = CV_ADAPTIVE_THRESH_GAUSSIAN_C; // CV_ADAPTIVE_THRESH_MEAN_C, CV_ADAPTIVE_THRESH_GAUSSIAN_C
    cv::adaptiveThreshold(src, src, 255, 
                          adaptiveMethod, CV_THRESH_BINARY, 
                          9, -5);

    int dilate_sz = 1;
    cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE,
                                       cv::Size(2*dilate_sz, 2*dilate_sz),
                                       cv::Point(dilate_sz, dilate_sz) );
    cv::dilate(src, src, element);
}

void detect_hand_silhoutte(cv::Mat& src)
{
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(7, 7), cv::Point(3, 3));
    cv::morphologyEx(src, src, cv::MORPH_ELLIPSE, kernel);        

    int adaptiveMethod = CV_ADAPTIVE_THRESH_MEAN_C; // CV_ADAPTIVE_THRESH_MEAN_C, CV_ADAPTIVE_THRESH_GAUSSIAN_C
    cv::adaptiveThreshold(src, src, 255, 
                          adaptiveMethod, CV_THRESH_BINARY, 
                          251, 5); // 251, 5

    int erode_sz = 5;
    cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE,
                                       cv::Size(2*erode_sz + 1, 2*erode_sz+1),
                                       cv::Point(erode_sz, erode_sz) );
    cv::erode(src, src, element);

    int dilate_sz = 1;
    element = cv::getStructuringElement(cv::MORPH_ELLIPSE,
                                       cv::Size(2*dilate_sz + 1, 2*dilate_sz+1),
                                       cv::Point(dilate_sz, dilate_sz) );
    cv::dilate(src, src, element);

    cv::bitwise_not(src, src);
}
于 2013-03-31T03:40:15.690 に答える