二值化图像数据

时间:2018-03-10 14:17:09

标签: python numpy image-processing computer-vision voxel

我从BrainWeb进行了10次灰度脑部MRI扫描。它们存储为4d numpy数组brains,形状为(10, 181, 217, 181)。 10个大脑中的每一个都由沿着z平面的181个切片(穿过头部顶部到颈部)组成,其中每个切片在x(耳朵到耳朵)和y(眼睛到z)中是181像素乘217像素。后面的飞机分别是飞机。

所有大脑都是dtype('float64')型。所有大脑的最大像素强度为~1328,最小值为~0。例如,对于第一个大脑,我通过brains[0].max()计算得出1328.338086605072brains[0].min()给出0.0003886114541273855。下面是brain[0]

的切片图

enter image description here

我想通过重新调整从[0, 1328]{0, 1} 的像素强度来对所有这些大脑图像进行二值化。 我的方法是否正确?

我首先将像素强度标准化为[0, 1]

normalized_brains = brains/1328 

然后使用二项分布对每个像素进行二值化:

binarized_brains = np.random.binomial(1, (normalized_brains))

绘制的结果看起来是正确的:

enter image description here

0像素强度表示黑色(背景),1像素强度表示白色(脑)。

我通过实现另一种方法来实现this post来规范化图像,但它只给了我一个黑色图像。这是因为np.finfo(np.float64)1.7976931348623157e+308,因此标准化步骤

normalized_brains = brains/1.7976931348623157e+308

刚刚返回了一个零数组,在二进制化步骤中也导致了一个零数组。

我是否使用正确的方法对图像进行二值化?

3 个答案:

答案 0 :(得分:1)

您是否尝试过图像阈值?

这是common way二值化图像,而不是尝试应用随机二项分布。你可以尝试类似的东西:

binarized_brains = (brains > threshold_value).astype(int)

根据图像值是否小于或大于您选择的阈值返回0和1的数组。

您必须尝试使用​​阈值来为图像找到最佳阈值,但不需要先对其进行标准化。

如果效果不佳,您还可以尝试使用skimage filters包中提供的阈值选项。

答案 1 :(得分:1)

将图像转换为二进制图像的方法基本上等于随机抖动,这是在二进制介质上创建灰度值错觉的不良方法。老式印刷品是一种二元媒介,他们对几百年来印刷中的灰色值照片进行了精细调整。此过程称为halftoning,部分由纸上墨水的属性决定,我们不必在二进制图像中处理。

那么人们在印刷品之外提出了哪些方法呢?有序抖动(主要是Bayer matrix)和error diffusion dithering。阅读更多关于维基百科上的抖动的信息。几年前我写了blog post showing how to implement all of these methods in MATLAB

我建议您为特定应用使用误差扩散抖动。以下是MATLAB中的一些代码(取自上面我喜欢的博客文章)中的Floyd-Steinberg算法,我希望你能将它翻译成Python:

img = imread('https://i.stack.imgur.com/d5E9i.png');
img = img(:,:,1);

out = double(img);
sz = size(out);
for ii=1:sz(1)
   for jj=1:sz(2)
      old = out(ii,jj);
      %new = 255*(old >= 128); % Original Floyd-Steinberg
      new = 255*(old >= 128+(rand-0.5)*100); % Simple improvement
      out(ii,jj) = new;
      err = new-old;
         if jj<sz(2)
            % right
            out(ii  ,jj+1) = out(ii  ,jj+1)-err*(7/16);
         end
      if ii<sz(1)
         if jj<sz(2)
            % right-down
            out(ii+1,jj+1) = out(ii+1,jj+1)-err*(1/16);
         end
            % down
            out(ii+1,jj  ) = out(ii+1,jj  )-err*(5/16);
         if jj>1
            % left-down
            out(ii+1,jj-1) = out(ii+1,jj-1)-err*(3/16);
         end
      end
   end
end

imshow(out)

enter image description here

在应用抖动之前重新采样图像可以大大改善结果:

img = imresize(img,4);
% (repeat code above)
imshow(out)

enter image description here

注意以上过程要求输入在[0,255]范围内。它很容易适应不同的范围,比如[0,1328]或[0,1],但也很容易将图像缩放到[0,255]范围。

答案 2 :(得分:0)

IT is easy in OpenCV. as mentioned a very common way is defining a threshold, But your result looks like you are allocating random values to your intensities instead of thresholding it. 

import cv2
im = cv2.imread('brain.png', cv2.CV_LOAD_IMAGE_GRAYSCALE)
(th, brain_bw) = cv2.threshold(imy, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
th = (DEFINE HERE)
im_bin = cv2.threshold(im, th, 255, cv
cv2.imwrite('binBrain.png', brain_bw)

brain

binBrain