在OpenCV中填充单色背景

在OpenCV中填充单色背景

本文介绍了在OpenCV中填充单色背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在OpenCV中编写一个程序,对寄生虫卵进行拍照,并尝试至少识别其中的大部分.我的问题是,我获得最佳效果的输入图像背景较大.我既尝试填充背景,又裁剪出背景,但是当我这样做的时候,我选择的蛋就变糟了.

I'm writing a program in OpenCV which takes a picture of parasite eggs and attempts to identify at least a large portion of them. My problem is that the input image I have the best results with has a large background. I've tried both filling in the background, and cropping it out, but when I do I get a worse selection of the eggs.

我目前正在考虑的解决方案是使用背景图像,然后将其填充.感觉很简单,因为我只想用黑色填充该圆以外的任何东西,但是我不确定如何实际执行操作.如果有人可以指出要使用的方法,或者有任何好的建议.

My currently thought out solution is to use the image with the background and then fill it in. It felt like it would be easy because I just want to fill anything outside of that circle with black, but I'm not sure how to actually perform the action. If anyone could point be toward a method to use, or any suggestions that would be great.

以下是图像外观的链接:

Here is a link to what the image looks like:

谢谢!

推荐答案

似乎您需要在图像的外部填充黑色,因为这样可以更容易地识别鸡蛋,因为它们将被隔离为白色.

It seems that you need the exterior of the image to be filled with black because it makes it easier to identify the eggs since they will be isolated in white.

但是,如果寄生虫卵神奇地显示为蓝色怎么办?我将在第二秒钟进行解释,但是这种方法将使您免于每次需要新样品时都点击图像的负担.待分析.

But what if the parasite eggs magically appeared as blue? I'll explain this in a second, but this approach would free you from the burden of clicking on the image every time a new sample needs to be analyzed.

我用C ++编写了答案,但是如果您遵循什么代码,我相信您可以将其快速转换为Python.

I wrote the answer in C++, but you if follow what the code does I'm sure you can quickly translate it to 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() );
        }
    }

此时 circular_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;
}

在窗口中显示的输出是:

此解决方案的优势在于,由于鸡蛋已经涂成蓝色,因此用户无需与应用程序进行交互即可方便鸡蛋的检测.

The advantage of this solution is that the user doesn't need to interact with the application to facilitate the detection of the eggs, since they are already painted in blue.

此后,可以在输出图片上执行其他操作,例如 cv::inRange() 隔离彩色对象从图像的其余部分开始.

After this, other operations can be done on the output image such as cv::inRange() to isolate colored objects from the rest of the image.

因此,为完成起见,我将再添加几行文本/代码,以说明从现在开始您可以做什么,以将鸡蛋与图像的其余部分完全隔离:

// 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 的外观是

这篇关于在OpenCV中填充单色背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 09:45