医学图像是16位灰度图,窗宽窗位一般是活动的,处理完图像后,返回一个合适的窗宽窗位是非常有必要的,阅览了知网的几篇论文,写了如下函数,很简单,原理是根据图像的直方图来调节的方法。
定义一个函数:
void Wadjust(Mat &src, ushort &WW, ushort &WL, double th)
src为输入图,WW,WL为窗宽和窗位输出,th为微调的参数,测试0.08-0.12都是比较好的。quality为粗定义图像的质量分数,项目需要,代码用下面方法二就可以了。上代码:
void Wadjust(Mat &src, ushort &WW, ushort &WL,int &quality, double th)
{
double sum = 0;
double num[MAXPIXEL+1] = { 0 };//MAXPIXEL =16384,255,65536看图像的位数去
double maxVal = 0;
double minVal = MAXPIXEL;
int left = 0; int right = 0; //窗宽的左边界和右边界
int pick = 0,pick_pos = 0; //存储直方图的峰值以及该峰值对应的直方图像素横坐标
//minMaxIdx(src, &minVal, &maxVal);
//计算直方图
for (auto i = 0; i < src.rows; i++)
for (auto j = 0; j < src.cols; j++)
{
ushort val = src.at<ushort>(i, j);
if (val > MAXPIXEL)
val = MAXPIXEL;
num[val] ++;
sum += val;
// 寻找图像像素的最大最小值,作为窗宽的粗范围
if (val >= maxVal)
{
maxVal = val;
}
if ((val != 0) && (val < minVal))
{
minVal = val;
}
//寻找直方图的峰点和峰点对应的像素横坐标
if((val!=0) && (num[val] >=pick))
{
pick = num[val];
pick_pos = val;
}
}
quality = (int)(100 * ((double)pick_pos / MAXPIXEL));
//std::cout << "直方图中的峰值横坐标: " << (int)(100 * ((double)pick_pos / MAXPIXEL)) << endl;
std::cout << "直方图中图像的峰值:" <<pick << endl;
//方法二:
double sum_hist = 0, sum_add = 0;
double wc = 0;
bool flag_left = 0;
bool flag_cc = 0;
for (int i = 0; i < MAXPIXEL; i++)
{
sum_hist += num[i];
}
for (int j = 0; j < MAXPIXEL; j++)
{
sum_add += num[j];
if (sum_add >= sum_hist *th && flag_left == false)
{
left = j;
flag_left = true;
}
if (sum_add >= sum_hist *0.72 && flag_cc == false) //论文中的经验系数0.72
{
wc = j;
flag_cc = true;
}
if (sum_add >= sum_hist *0.98)//0.97
{
right = j;
break;
}
}
WW = right - left;
int ff = WW / 2 + left;
WL = (ff< wc) ? ff : wc;
return;
}