1

私は、寄生虫の卵の写真を撮り、少なくともその大部分を特定しようとするプログラムを OpenCV で書いています。私の問題は、最良の結果を得た入力画像の背景が大きいことです。背景の塗りつぶしとトリミングの両方を試みましたが、そうすると卵の選択が悪くなります。

私が現在考えている解決策は、背景のある画像を使用してから塗りつぶすことです。その円の外側を黒で塗りつぶしたいだけなので簡単だと感じましたが、実際にどのように実行するかわかりませんアクション。誰かが使用する方法や素晴らしい提案を指摘できれば.

画像がどのように見えるかへのリンクは次のとおりです。

ここに画像の説明を入力

ありがとう!

4

2 に答える 2

1

私の問題の修正を行い、クリックしたものを黒で塗りつぶすマウスイベントコールバックを作成しました。以下は、コールバックで使用したコードです。

def paint(event, x, y, flags, param):
    global opening                                                                                                                         

    if event == cv2.EVENT_LBUTTONDOWN:
        h, w = opening.shape[:2]
        mask = np.zeros((h+2, w+2), np.uint8)
        cv2.floodFill(opening, mask, (x,y), (0, 0, 0)) 
        cv2.imshow("open", opening)
于 2013-11-14T02:27:17.180 に答える
1

画像の外側を黒で塗りつぶす必要があるようです。これは、卵が白で分離されるため、卵を識別しやすくするためです。

しかし、寄生虫の卵が魔法のように青く見えたらどうなるでしょうか? これについてはすぐに説明しますが、このアプローチにより、新しいサンプルを分析する必要があるたびに画像をクリックする負担から解放されます。

私は答えを C++ で書きましたが、コードの動作に従えば、すぐに Python に変換できると確信しています。

#include <iostream>
#include <vector>

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>


int main(int argc, char* argv[])
{
    // Load input image (3-channel)
    cv::Mat input = cv::imread(argv[1]);
    if (input.empty())
    {
        std::cout << "!!! failed imread()" << std::endl;
        return -1;
    }   

    // Convert the input to grayscale (1-channel)
    cv::Mat grayscale = input.clone();
    cv::cvtColor(input, grayscale, cv::COLOR_BGR2GRAY);

この時点でのグレースケールは次のようになります。

    // Locate the black circular shape in the grayscale image
    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(grayscale, contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);

    // Fill the interior of the largest circular shape found with BLUE
    cv::Mat circular_shape = input.clone();
    for (size_t i = 0; i < contours.size(); i++)
    {
        std::vector<cv::Point> cnt = contours[i];
        double area = cv::contourArea(cv::Mat(cnt));        

        if (area > 500000 && area < 1000000) // magic numbers to detect the right circular shape
        {
            std::cout << "* Area: " << area << std::endl;
            cv::drawContours(circular_shape, contours, i, cv::Scalar(255, 0, 0), 
                             cv::FILLED, 8, std::vector<cv::Vec4i>(), 0, cv::Point() );
        }           
    }   

この時点での circle_shapeは次のようになります。

    // Create the output image with the same attributes of the original, i.e. dimensions & 3-channel, so we have a colored result at the end
    cv::Mat output = cv::Mat::zeros(input.size(), input.type());

    // copyTo() uses circular_shape as a mask and copies that exact portion of the input to the output
    input.copyTo(output, circular_shape);

    cv::namedWindow("Eggs", cv::WINDOW_NORMAL | cv::WINDOW_KEEPRATIO);  
    cv::imshow("Eggs", output);
    cv::resizeWindow("Eggs", 800, 600);
    cv::waitKey(0);

    return 0;
}

ウィンドウに表示される出力は次のとおりです。

このソリューションの利点は、卵が既に青色に塗られているため、卵の検出を容易にするためにユーザーがアプリケーションと対話する必要がないことです。

この後、画像の残りの部分から色付きのオブジェクトを分離するなど、出力画像に対して他の操作を実行できます。cv::inRange()

したがって、完成させるために、テキスト/コードをさらに数行追加して、この時点から卵を画像の残りの部分から完全に分離するために何ができるかを示します。

// Isolate blue pixels on the output image
cv::Mat blue_pixels_only;
cv::inRange(output, cv::Scalar(255, 0, 0), cv::Scalar(255, 0, 0), blue_pixels_only);

この段階でblue_pixels_onlyがどのように見えるか:

// Get rid of pixels on the edges of the shape 
int erosion_type = cv::MORPH_RECT; // MORPH_RECT, MORPH_CROSS, MORPH_ELLIPSE
int erosion_size = 3;
cv::Mat element = cv::getStructuringElement(erosion_type, 
                                            cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1), 
                                            cv::Point(erosion_size, erosion_size));
cv::erode(blue_pixels_only, blue_pixels_only, element);
cv::dilate(blue_pixels_only, blue_pixels_only, element);

cv::imshow("Eggs", blue_pixels_only);
cv::imwrite("blue_pixels_only.png", blue_pixels_only);

この段階でblue_pixels_onlyがどのように見えるか:

于 2013-11-14T22:25:40.063 に答える