有些时候碰到的Dicom数据中的tag值是标错的,本来需要进行Inverse的图像,但是在Tag的相应字段并没有标出,导致dicom中的图像内容在进行后续处理时没有进行反色而导致后续算法计算错误。
比如需要反色的下图:
这时候就需要基于图像本身的性质来建立自适应的判断为最终反色与否再把一道关。
根据图像本身的性质进行反色基于一下一点假设: DR中的人体成分占整张图像的绝大多数
这个假设的正确与否可以做一个逆推过程:如果一张用于给医生看的DR中人体成分并不占大多数,即DR主要拍摄的是空气,我觉得这张图首先就是有问题的,因此反不反色根本没有意义。
那么现在的问题在这里就简单了,反色的原因是为了凸显人体组织,使得高密度的人体组织看起来比周围的空气更加亮而已;那么算法的设计可以有以下两个部分:1. 找到主要成分(默认就是人体)所占的灰度值范围 2. 判断位于图像边缘(默认就是图像四个角,这里需要考虑四个角,因为有些时候会在左上角打上一个R或是L的标签)中有没有不属于主要成分灰度范围内,但是又明显大于范围的值,如果有的话,需要反向。对于第一个部分直接使用灰度累积分布函数即可获知灰度范围,对于第二个部分直接进行小区域的均值比较即可,整个算法两个超参:1. 判断主成分的阈值 2. 小区域的边长
现在将Python 代码公布如下,最终使用judge_inverse 判断是否需要反色:
import numpy as np import cv2 import os def getCH(img,nbins=256): ''' TODO: get img Cumulative distribution histogram :param img: ndarray input image :param nbins: integer histogram bins :return ch: ndarray result of Cumulative distribution histogram ''' # get image histogram imgmax = img.max() imgmin = img.min() hist,bins = np.histogram(img.flatten(),nbins,[imgmin,imgmax]) area = img.shape[0]*img.shape[1] # calculate cumulative histogram cdf = hist.cumsum() cdf_normalized = cdf /area # get normalized cumulative distribution histogram return cdf_normalized, bins def getMajorGrey(nbins,cd_normalized,th): ''' TODO: get img majority object grey intensity distribution :param img: :param nbins: :param cd_normalized: :return: ''' th_min = th th_max = 1.0 - th cd_normalized = np.array(cd_normalized) index_th_min = np.where(cd_normalized > th_min)[0][0] index_th_max = np.where(cd_normalized > th_max)[0][0] major_min = nbins[index_th_min].astype(np.uint16) major_max = nbins[index_th_max].astype(np.uint16) return major_max, major_min def judge_inverse(img,max): ''' TODO: 根据四角判断是否局域主要成分的上位,如果是就进行反色,返回flag :param img: :param max: :param min: :return: ''' row, col = img.shape block1 = img[0:10, 0:10] block2 = img[row-10:row, 0:10] block3 = img[0:10, col-10:col] block4 = img[row-10:row, col-10:col] m1 = np.mean(block1) m2 = np.mean(block2) m3 = np.mean(block3) m4 = np.mean(block4) Flag = False if m1 >= max: Flag = True if m2 >= max: Flag = True if m3 >= max: Flag = True if m4 >= max: Flag = True return Flag