Python 二值图像的边缘平滑

Python 二值图像的边缘平滑,python,opencv,image-processing,blur,smoothing,Python,Opencv,Image Processing,Blur,Smoothing,如何平滑阈值化后获得的血管二值图像的边缘 我尝试了一种有点类似的方法,但没有达到我预期的效果 代码如下: import cv2 import numpy as np INPUT = cv2.imread('so-br-in.png',0) MASK = np.array(INPUT/255.0, dtype='float32') MASK = cv2.GaussianBlur(MASK, (5,5), 11) BG = np.ones([INPUT.shape[0], INPUT.sha

如何平滑阈值化后获得的血管二值图像的边缘

我尝试了一种有点类似的方法,但没有达到我预期的效果

代码如下:

import cv2
import numpy as np

INPUT = cv2.imread('so-br-in.png',0)
MASK = np.array(INPUT/255.0, dtype='float32')

MASK = cv2.GaussianBlur(MASK, (5,5), 11)
BG = np.ones([INPUT.shape[0], INPUT.shape[1], 1], dtype='uint8')*255

OUT_F = np.ones([INPUT.shape[0], INPUT.shape[1], 1],dtype='uint8')

for r in range(INPUT.shape[0]):
    for c in range(INPUT.shape[1]):
        OUT_F[r][c]  = int(BG[r][c]*(MASK[r][c]) + INPUT[r][c]*(1-MASK[r][c]))

cv2.imwrite('brain-out.png', OUT_F)  
cv::Mat vesselImage = cv::imread(filename); //the original image
cv::threshold(vesselImage, vesselImage, 125, 255, THRESH_BINARY);
cv::Mat blurredImage; //output of the algorithm
cv::pyrUp(vesselImage, blurredImage);

for (int i = 0; i < 15; i++)
    cv::medianBlur(blurredImage, blurredImage, 7);

cv::pyrDown(blurredImage, blurredImage);
cv::threshold(blurredImage, blurredImage, 200, 255, THRESH_BINARY);
如何改善这些粗糙边缘的平滑度

编辑


我想把边缘弄光滑一些。如何在OpenCV中执行此操作?

您可以扩张然后侵蚀这些区域


在填充之前使用缩放因子4进行编辑

您可以做的是提高图像的分辨率(例如,使用
调整大小
将其加倍或三倍)。之后,上面另一个答案中描述的侵蚀和膨胀将导致更精细的结果。

以下是我从您的图像中获得的结果:

我的方法主要基于几个应用于放大图像的
cv::medianBlur

代码如下:

import cv2
import numpy as np

INPUT = cv2.imread('so-br-in.png',0)
MASK = np.array(INPUT/255.0, dtype='float32')

MASK = cv2.GaussianBlur(MASK, (5,5), 11)
BG = np.ones([INPUT.shape[0], INPUT.shape[1], 1], dtype='uint8')*255

OUT_F = np.ones([INPUT.shape[0], INPUT.shape[1], 1],dtype='uint8')

for r in range(INPUT.shape[0]):
    for c in range(INPUT.shape[1]):
        OUT_F[r][c]  = int(BG[r][c]*(MASK[r][c]) + INPUT[r][c]*(1-MASK[r][c]))

cv2.imwrite('brain-out.png', OUT_F)  
cv::Mat vesselImage = cv::imread(filename); //the original image
cv::threshold(vesselImage, vesselImage, 125, 255, THRESH_BINARY);
cv::Mat blurredImage; //output of the algorithm
cv::pyrUp(vesselImage, blurredImage);

for (int i = 0; i < 15; i++)
    cv::medianBlur(blurredImage, blurredImage, 7);

cv::pyrDown(blurredImage, blurredImage);
cv::threshold(blurredImage, blurredImage, 200, 255, THRESH_BINARY);
cv::Mat vesselImage=cv::imread(文件名)//原始图像
cv::阈值(vesselImage,vesselImage,125,255,THRESH_二进制);
cv::Mat blurredImage//算法的输出
cv::pyrUp(vesselImage,blurredImage);
对于(int i=0;i<15;i++)
cv::medianBlur(模糊图像,模糊图像,7);
cv::pyrDown(模糊图像,模糊图像);
cv::阈值(模糊图像,模糊图像,200,255,阈值二进制);

锯齿状边缘是由于阈值分割造成的。如果您对非二值化的输出图像(即256灰度)感到满意,您只需将其删除即可获得此图像:

您很可能首先获得血管的灰度图像,然后对其进行阈值处理。它仍然看起来不平滑,因为原始灰度图像内部有噪声。现在要求平滑边缘将导致分辨率降低。例如,中提出的稀释和侵蚀可能会在稀释步骤中熔合相邻容器,然后在侵蚀步骤中无法再次分离

最好先去除灰度图像中的噪声(也就是在那里进行平滑处理),然后作为最后一步进行阈值处理

因为您没有提供灰度图像,所以我在二值图像上执行了轻度平滑(大约一个像素宽度),然后再次执行阈值处理

我做了平滑处理(使用固定大小的高斯核)和阈值处理(使用阈值参数)。我建议您在灰度图像数据上这样做,并调整这两个参数,直到您喜欢结果为止

Matlab代码(如果感兴趣):

% read
img = imread('YyNQV.png');
img = double(img(:, :, 1) ~= 255); % png is RGB -> binary

% smooth
kernel = fspecial('gaussian', 10, 1.5);
kernel = kernel / sum(kernel(:)); % normalize to 1
img_smooth = conv2(img, kernel, 'same');

% binarize again
threshold = 0.4; % experiment with values between 0 and 1
img_smooth_threshold = img_smooth > threshold;

% save (exchange black and white)
imwrite(~img_smooth_threshold, 'YyNQV_smooth.png');

我在@dhanushka上做了一些修改,得到了这些图片

对不起,它是C++代码,但也许你会把它转换成Python。

您可以更改以下参数以获得不同的结果

// contour smoothing parameters for gaussian filter
int filterRadius = 10; // you can try to change this value
int filterSize = 2 * filterRadius + 1;
double sigma = 20; // you can try to change this value

#包括
#包括
#包括
使用名称空间cv;
使用名称空间std;
int main(int argc,常量字符**argv)
{
Mat im=imread(argv[1],0);
Mat cont=~im;
Mat original=Mat::零(im.rows、im.cols、CV_8UC3);
Mat平滑=Mat(im.rows,im.cols,CV_8UC3,标量(255255));
//高斯滤波器的轮廓平滑参数
int filteradius=5;
int filterSize=2*filterRadius+1;
双西格玛=10;
矢量等值线;
向量层次;
//查找轮廓并存储所有轮廓点
findContours(cont,等高线,层次结构,CV_RETR_CCOMP,CV_CHAIN_近似值,无,点(0,0));
对于(大小j=0;j
Hi。如果可能的话,你能发布一些示例代码和结果吗?这就是我的意思!由于你的内核大小不同,腐蚀和膨胀,你几乎使他的轮廓膨胀不确定这是否是理想的结果。源图像非常糟糕,所以。。。这是我感觉最好的,但我把参数放在外面,让他调整。这当然更好,但即使在这张图片中,边缘也不是很平滑。你能告诉我如何平滑这些边缘吗?看看这是否是你想要的。试着在垫子上使用numpy操作它比逐像素操作要快得多也许你可以更详细地描述你所期望的…@dhanushka对我的图像不起作用。如果您还有其他想法,请分享。:)@安东尼奥:我们的大脑有联系吗?我刚刚用4的比例因子完成了这项工作,效果更好,但是用我们手中的新源图像我们可以做得更好:)这是一个更好的结果。我对你的答案投了更高的票,如果我在接下来的几天里没有得到更好的答案,我会接受这个答案。在这篇文章中,唯一实际应用的操作是高斯模糊。然后他调整水平以获得更锐利的边缘。在您的情况下,图像中的缺陷太明显,无法纠正