Remove spurious small islands of noise in an image - Python OpenCV

Remove spurious small islands of noise in an image - Python OpenCV,第1张

Remove spurious small islands of noise in an image - Python OpenCV

你的很多问题都是因为你不知道该怎么做
形态学图像处理工作,但我们可以消除你的疑虑。你呢
可以把结构元素解释为“基本形态”来比较。1英寸
结构元素对应于要在中查看的像素
此形状和0是您要忽略的形状。有不同的形状,例如
矩形(如你用“变形矩形”算出的),椭圆,圆形,
等。
因此,

cv2.getStructuringElement
为您返回一个结构元素。
第一个参数指定所需的类型,第二个参数指定所需的类型
指定所需的大小。在你的例子中,你想要一个2 x 2“的矩形。。。
这真的是个正方形,但没关系。
在一个更低级的意义上,您使用结构化元素并从
从左到右,从上到下抓取像素
邻里。每个像素邻域的中心正好位于像素上
你正在看的有趣的东西。每个像素邻域的大小是
与结构元素大小相同。

侵蚀

对于侵蚀,检查像素邻域中
正在触及结构元素。如果每个非零像素都在接触
结构元素像素为1,然后是
与输入相对应的中心位置为1。如果有
至少一个接触的非零像素
1,则输出为0。
对于矩形结构元素,您需要确保
结构元素中的每一个像素都会接触到一个非零像素
像素邻域的图像。如果不是,则输出为0,否则为1。
这有效地消除了噪声的小杂散区域,也降低了噪声
物体的面积。
矩形越大,收缩越大
执行。结构元素的大小是任何对象
比这个矩形结构元素小,你可以考虑
它们被过滤掉而不出现在输出中。基本上,选择一个
1 x 1矩形结构元素与输入图像本身相同
因为这个结构元素适合它里面的所有像素,因为像素是
图像中可能的最小信息表示。

扩张

膨胀与侵蚀相反。如果至少有一个非零像素
结构元素中的像素是1,那么在结构元素中的像素是1
1,否则输出为0。你可以认为这是一个稍微放大的物体
扩大小岛面积。
这里的大小意味着结构元素越大,
物体的面积越大,孤立的物体就越大
岛屿变成了。


你要做的是先腐蚀然后扩张。这就是
被称为打开 *** 作。此 *** 作的目的是移除
小岛的噪音,同时(试图)保持较大的面积
图像中的对象。侵蚀移除了这些岛屿,而膨胀
将较大的对象恢复到其原始大小。
因为某种原因,你又一次被侵蚀了,我不太明白
明白,但没关系。


我个人会做的是先执行关闭 *** 作,这是一个
膨胀之后是腐蚀。关闭有助于对靠近的区域进行分组
一起变成一个物体。因此,你看到有一些更大的
在我们彼此接近之前
别的。因此,我会先做一个结束,然后做一个开始
之后,我们可以消除孤立的噪音区域。注意我要走了
为了使结束结构元素的大小更大,我想确定
我得到附近的像素和开口结构元素的大小所以
我不想错误地移除任何较大的区域。
一旦你这么做了,我会用原件掩盖任何额外的信息
这样你就可以在小岛离开的时候保持较大的区域完好无损
走开。
而不是把腐蚀和膨胀联系起来
由于侵蚀,使用

cv2.morphologyEx
,
其中可以指定“MORPHu OPEN”和“MORPHu CLOSE”作为标志。
因此,我个人会这样做,假设你的形象是所谓的
斑点.png
:

import cv2import numpy as npimg = cv2.imread('spots.png')img_bw = 255*(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) > 5).astype('uint8')se1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))se2 = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))mask = cv2.morphologyEx(img_bw, cv2.MORPH_CLOSE, se1)mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, se2)mask = np.dstack([mask, mask, mask]) / 255out = img * maskcv2.imshow('Output', out)cv2.waitKey(0)cv2.destroyAllWindows()cv2.imwrite('output.png', out)

上面的代码非常简单。首先,我读入图像,然后
我将图像转换为灰度和阈值,强度为5到
创建被视为对象像素的遮罩。这是一个相当干净的房间
所以任何大于5的东西似乎都起作用了。对于形态学
我需要转换图像。
接下来,我们创建两个结构元素-一个是一个5 x 5的矩形
关闭 *** 作和另一个2 x 2的打开 *** 作。我
运行“cv2.morphologyEx”两次以执行打开和关闭 *** 作
分别在阈值图像上。
一旦我这样做了,我堆叠的面具,使它成为一个三维矩阵和除以
所以它变成了一个

[0,1]
的掩码,然后我们把这个掩码乘以
这样我们就可以抓取图像的原始像素了
以及从掩码输出中保持被认为是真实对象的内容。
剩下的只是举例说明。我在窗口中显示图像,并且
将图像保存到名为
输出.png
,其目的是向您展示
这张照片是什么样子的。
我明白了:记住它并不完美,但它比你拥有它的方式要好得多
以前。你将不得不玩弄结构元素的大小来获得
你认为这是一个很好的输出,但这肯定足以
开始吧。祝你好运!


α+C版本
已经有一些请求把上面写的代码翻译成C

使用OpenCV的版本。我终于开始写一个C++版本了
代码和它已经在opencv3.1.0上进行了测试。代码如下。
如您所见,代码与Python版本中的代码非常相似。
但是,我用

cv::Mat::setTo

在原始图像的副本上设置任何不是最终图像的部分
屏蔽为0。这与执行元素乘法是一样的
在Python中。

#include <opencv2/opencv.hpp>using namespace cv;int main(int argc, char *argv[]){    // Read in the image    Mat img = imread("spots.png", CV_LOAD_IMAGE_COLOR);    // Convert to black and white    Mat img_bw;    cvtColor(img, img_bw, COLOR_BGR2GRAY);    img_bw = img_bw > 5;    // Define the structuring elements    Mat se1 = getStructuringElement(MORPH_RECT, Size(5, 5));    Mat se2 = getStructuringElement(MORPH_RECT, Size(2, 2));    // Perform closing then opening    Mat mask;    morphologyEx(img_bw, mask, MORPH_CLOSE, se1);    morphologyEx(mask, mask, MORPH_OPEN, se2);    // Filter the output    Mat out = img.clone();    out.setTo(Scalar(0), mask == 0);    // Show image and save    namedWindow("Output", WINDOW_NORMAL);    imshow("Output", out);    waitKey(0);    destroyWindow("Output");    imwrite("output.png", out);}

The results should be the same as what you get in the Python version.



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5630555.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存