python - 在 OpenCV 中填充单色背景

标签 python opencv

我正在用 OpenCV 编写一个程序,该程序拍摄寄生虫卵的照片并尝试至少识别其中的大部分。我的问题是我获得最佳结果的输入图像具有较大的背景。我试过填充背景和裁剪背景,但当我这样做时,我选择的鸡蛋更差。

我目前想到的解决方案是使用带有背景的图像然后填充它。感觉这很容易,因为我只想用黑色填充那个圆圈之外的任何东西,但我不确定如何实际执行操作。如果有人能指出一种使用方法或任何建议,那就太好了。

这是图片的链接:

enter image description here

谢谢!

最佳答案

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

但是,如果寄生虫卵神奇地显示为蓝色怎么办?我稍后会对此进行解释,但这种方法可以让您免于每次需要新样本时都点击图像的负担待分析。

我用 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() );
        }           
    }   

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

窗口上显示的输出是:

此解决方案的优点是用户无需与应用程序交互来促进鸡蛋的检测,因为它们已经被涂成蓝色。

在此之后,可以对输出 图像进行其他操作,例如cv::inRange()isolate colored objects来自图像的其余部分。

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

// 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 在这个阶段看起来像什么:

关于python - 在 OpenCV 中填充单色背景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19966423/

相关文章:

python - numpy中十进制整数数组到二进制数组的矢量化转换

python - 更改日期范围并循环运行

c++ - 使用 CMakeLists.txt 构建 qt 编译输出 make : *** No rule to make target `all' . Stop

opencv - 使用 DummyData 层 : "Can' t create layer "DummyData1" of type "DummyData1" in function 'getLayerInstance' "加载 Caffe 模型时出错

python - 使用 OpenCV Python 检测对象

python - 为什么 dnspython 模块会给出 LifetimeTimeout 错误?

Python for .NET : System. BadImageFormatException 嵌入时

python - 使用python从重定向的标准输入读取文件

android - Android 上的 OpenCV 支持

python - 语法错误: invalid syntax while trying to release webcam