从X射线图像中提取手骨 [英] Extract hand bones from X-ray image

查看:165
本文介绍了从X射线图像中提取手骨的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一只手的X射线图像。我需要自动提取骨骼。我可以使用不同的技术轻松分割手。但我需要得到骨头并使用这些技术无济于事。有些骨头比其他骨头更明亮,所以如果我使用阈值处理,其中一些骨头会消失,而其他骨骼则会变得更清晰。我想也许我应该只限制一个手的区域?是否可以达到非正方形的ROI?哦,也许你有任何其他解决方案,建议?也许有一些像OpenCV这样的图书馆?任何帮助都会非常棒!

I have x-ray image of a hand. I need to extract bones automatically. I can easily segmentate a hand using different techniques. But I need to get bones and using those techniques don't help. Some of the bones are brighter then orthers, so if I use thresholding some of them disapear while others become clearer rising threshold. And I think maybe I should threshold a region of the hand only? Is it possible to threshold ROI that is not a square? O maybe you have any other solutions, advices? Maybe there are some libraries like OpenCV or something for that? Any help would be very great!

扩展:


                ;   原始图片                        预期输出

                 Raw Image                      Expected Output

推荐答案

一种方法可能是从图像中分割手和手指

然后使用手形轮廓创建另一个图像:

And then creating another image with just the hand silhouette:

在你有你可以侵蚀图像的轮廓,使它变得更小。这用于手&中减去手。手指图像,导致手指:

Once you have the silhouette you can erode the image to make it a little smaller. This is used to subtract the hand from the hand & fingers image, resulting in the fingers:

以下代码显示执行此方法:

The code below shows to execute this approach:

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);
}

这篇关于从X射线图像中提取手骨的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆