在OpenCV中填充单色背景

2024-06-26 02:08:26 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我目前考虑的解决方案是使用带有背景的图像,然后填充它。感觉很简单,因为我只想用黑色填充圆圈之外的任何东西,但我不确定如何实际执行这个动作。如果有人能指出一个方法,或任何建议,将是伟大的。在

以下是图像外观的链接:

enter image description here

谢谢!在


Tags: 方法图像程序解决方案opencv鸡蛋建议照片
2条回答

看起来你需要图像的外部填充黑色,因为这样更容易识别鸡蛋,因为它们将被隔离为白色。在

但是如果寄生虫卵神奇地变成蓝色呢?我稍后将对此进行解释,但这种方法将使您从每次需要分析新样本时单击图像的负担中解脱出来。在

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

此时,灰度是什么样子:

^{pr2}$

此时,圆形是什么样子:

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

窗口上显示的输出为:

这个解决方案的优点是,用户不需要与应用程序交互以方便检测鸡蛋,因为它们已经被涂成蓝色。在

在此之后,可以对输出图像执行其他操作,例如从图像的其余部分^{}到{a2}。在

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

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

在此阶段,仅蓝色像素是什么样子:

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

在此阶段,仅蓝色像素是什么样子:

解决了我的问题,我创建了一个鼠标事件回调函数,用黑色填充我单击的任何内容。下面是我在回调中使用的代码:

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)

相关问题 更多 >