Extract hand bones from X-ray image

前端 未结 1 468
死守一世寂寞
死守一世寂寞 2021-02-06 10:01

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 technique

1条回答
  •  时光说笑
    2021-02-06 10:33

    One approach could be to segment the hand and fingers from the image:

    enter image description here

    And then creating another image with just the hand silhouette:

    enter image description here

    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:

    enter image description here

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

    0 讨论(0)
提交回复
热议问题