《深度学习与医学图像处理》【学习分享5】医学数字图像的数据预处理
<div class='showpostmsg'><p>在实际应用场景中,获取的原始数据可能会存在一些问题,例如图片尺寸、对比度不统一等,需要进行一些预处理,才能用于模型的训练。</p><p> </p>
<p>一、扩展库安装</p>
<p>通过本书第4章的学习,了解到,通常会使用SimpleTK、NumPy、sickit-image、TensorFlow等库进行处理。</p>
<p>要使用这些库进行处理,需要先使用pip进行安装:</p>
<pre>
<code class="language-bash">pip install SimpleITK
pip install scikit-image
pip install elasticdeform
pip install tensorflow
</code></pre>
<p>另外,还有些安装一些图形处理库,方便可视化:</p>
<pre>
<code>pip install pillow
pip instal matplotlib
pip install python-opencv</code></pre>
<p> </p>
<p>二、导入需要使用的库</p>
<p>然后就可以在代码中,引入响应的库,以便后续代码调用:</p>
<pre>
<code class="language-python">import math
import SimpleITK as sitk
import matplotlib.pyplot as plt
import numpy as np
import elasticdeform as edf
from skimage import measure, color, morphology, transform, exposure, data, io
import tensorflow as tf
from PIL import Image
import cv2</code></pre>
<p> </p>
<p>三、数据预处理</p>
<p>1. 插值:</p>
<p>插值法是很常见的图像处理算法,通常使用最邻近插值法和双线性插值法。</p>
<p> </p>
<p>最邻近插值法是最简单的插值法,基本原理如下图:</p>
<p> </p>
<p>双线性插值法的原理如下图:</p>
<p> </p>
<div style="text-align: center;"></div>
<div style="text-align: center;"> </div>
<div>其原理效果效果如下:</div>
<div style="text-align: center;"> </div>
<p> </p>
<p> </p>
<p>两重插值法对应的代码如下:</p>
<pre>
<code class="language-python"># 采用最近插值法或线性插值法
def Linear_interpolation(img, target_shape, interpolation_method):
if interpolation_method == 'nearest_neighbor':
return transform.resize(img, target_shape, order=0, preserve_range=True)
elif interpolation_method == 'bilinear':
return transform.resize(img, target_shape, order=1, preserve_range=True)
else:
raise NameError('Undefined Method.')</code></pre>
<p> </p>
<p>我是用了一张颅内CT检查的DICOM样本数据来进行测试,结合之之前的代码,进一步进行处理:</p>
<pre>
<code># 图片转换为SimpleITK图片格式
skit_img = img_as_float(np.asarray(final_image))
# 调用最近邻插值法处理
nearest_neighbor_img = Linear_interpolation(skit_img, (512, 512), 'nearest_neighbor')
# 调用双线性插值法处理
biliner_img = Linear_interpolation(skit_img, (512, 512), 'bilinear')
# 存储图片
cv_image1 = img_as_ubyte(nearest_neighbor_img)
cv2.imwrite("1.jpg", cv_image1)
cv_image2 = img_as_ubyte(biliner_img)
cv2.imwrite("2.jpg", cv_image1)
# 显示图片
plt.figure()
plt.subplot(2,2,1)
plt.imshow(np.asarray(final_image),cmap='gray')
plt.subplot(2,2,3)
plt.imshow(nearest_neighbor_img,cmap='gray')
plt.subplot(2,2,4)
plt.imshow(biliner_img,cmap='gray')
plt.show()
</code></pre>
<p> </p>
<p>不过上面的图片中,可能看不到较为显著的差别,需要进一步放大,才能看到差异。</p>
<p> </p>
<p>2. 重采样</p>
<p>根据采样设备的不同,获取的数医学图像的像素间距可能存在差异,这就需要进行预处理,重采样为统一标准的图像,以便进行训练。</p>
<p>重采样的时候,还需要考虑使用合理的插值算法:真实尺寸 = 像素个数 * 像素间距</p>
<p>医学数据重采样常见的算法如下:</p>
<pre>
<code class="language-python"># 重采样
def Resample(sitkimg, spacing = None, resolution=None, interpolation = 0):
spacing_ori = np.array(sitkimg.GetSpacing())
resolution_ori = np.array(sitkimg.GetSize())
inte = sitk.sitkNearestNeighbor if interpolation == 0 else sitk.sitkLinear
if spacing:
f = spacing_ori / spacing
resolution = np.int32(np.round(resolution_ori * f))
elif resolution:
resolution = np.array(resolution)
f = resolution / resolution_ori
spacing = spacing_ori / f
else:
return sitkimg
origin = np.array(0.5 * (spacing - spacing_ori) / spacing_ori)
origin = sitkimg.TransformContinuousIndexToPhysicalPoint(origin)
rs = sitk.ResampleImageFilter()
rs.SetOutputSpacing(spacing)
rs.SetOutputOrigin(origin)
rs.SetSize(resolution.tolist())
rs.SetOutputDirection(sitkimg.GetDirection())
rs.SetOutputPixelType(sitkimg.GetPixelID())
rs.SetInterpolator(inte)
rs_sitkimg = rs.Execute(sitkimg)
return rs_sitkimg</code></pre>
<p> </p>
<p>继续使用前面的原始图像数据,将原始图片,转换为像素间距为(0.5, 0.5)的数据,对应的调用代码如下:</p>
<pre>
<code>origin = np.array(final_image)
skitimg_origin = sitk.GetImageFromArray(origin)
plt.figure()
plt.subplot(1,2,1)
plt.imshow(sitk.GetArrayFromImage(skitimg_origin),cmap='gray')
# plt.show()
spacing_ori = np.array(skitimg_origin.GetSpacing())
resolution_ori = np.array(skitimg_origin.GetSize())
print("spacing_ori: ", spacing_ori)
print("resolution_ori: ", resolution_ori)
skit_img_resample = Resample(skitimg_origin, spacing = (0.5, 0.5), resolution = None, interpolation = 0)
plt.subplot(1,2,2)
plt.imshow(sitk.GetArrayFromImage(skit_img_resample),cmap='gray')
plt.show()
</code></pre>
<p> </p>
<p>实际处理后的效果如下:</p>
<p> </p>
<p>上面的结果中,两个图看起来一样,但是从图像的刻度可以看到,像素间距已经不同了。</p>
<p> </p>
<p>3. 信号强度直方图的分析和均衡化</p>
<p>根据采样设备的不同,获取的数医学图像的信号强度也会存在差异,导致强度分布不统一。</p>
<p>这就需要使用到信号强度分析和处理,可以试用Matplotlib和Skimage进行信号强度的处理,对应的代码如下:</p>
<pre>
<code class="language-python"># 信号强度直方图的均衡化
def Histogram_equalization(img):
# 显示原图像
plt.subplot(2,2,1)
plt.imshow(img, cmap='gray')
plt.gca().invert_yaxis()
# plt.show()
# 显示原图像信号强度
plt.subplot(2,2,2)
n, bins, patches = plt.hist(img, bins=5, facecolor='red', alpha=0.75)
# plt.show()
# 信号强度直方图的均衡化和可视化
img_res = exposure.equalize_hist(img)
plt.subplot(2,2,3)
plt.imshow(img_res, cmap='gray')
plt.gca().invert_yaxis()
# plt.show()
# 显示均衡化后的信号强度直方图
plt.subplot(2,2,4)
n, bins, patches = plt.hist(img_res, bins=5, facecolor='red', alpha=0.75)
# plt.show()
return img_res</code></pre>
<p> </p>
<p>对应的调用代码如下:</p>
<pre>
<code>plt.figure()
skitimg_res = Histogram_equalization(sitk.GetArrayFromImage(skitimg_origin))
plt.show()</code></pre>
<p>最终的结果如下:</p>
<p> 从上图可以看到,原有图像较暗,处理后的图像对比度提高,能够更好的进行分析处理。</p>
<p> </p>
<p> </p>
<p>医学图像数据处理中,还包括数据归一化、连通域分析、形态学方法处理等,这里就不一一展示了。</p>
<p>经过合适的数据处理,就能够让原始的数据变得统一规范,方便后续的训练操作了。</p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页:
[1]