一、摘要

        本实验使用了opencv Mat类,逐像素访问及修改方法,滚动条及鼠标操作,最终实现了窗宽窗位调节。

二、实验内容:

1. 设计实现一个软件,利用OpenCV一种逐像素访问方法实现图像的窗口窗位调节显示。

2. 基于highgui的鼠标事件实现医学图像的窗口窗位调节。

三、算法流程:

python opencv窗宽窗位 opencv显示窗口调整大小_灰度

四、代码解析:

        实验中首先需要明确何为窗宽窗位。简单的说,正常情况下8位灰度图像素取值为0~255,这也是最普遍使用的图像灰度量化范围;而医学图像灰度范围为0~几千,于是我们需要一个线性映射将一定范围内的源医学图像灰度映射到0~255中。

        如下图所示,窗宽可以理解为这个范围的中心,窗宽为这个范围大小。

python opencv窗宽窗位 opencv显示窗口调整大小_python opencv窗宽窗位_02

         代码中的实现如下:

show.at<uchar>(i, j) = saturate_cast<uchar>(float(255)/short(width)*(frame.at<short>(i, j)-(level-width/2)));

         saturate_cast<uchar>为饱和截断,保证灰度值在0~255。值得注意的是,原图像的像素值范围要远大于255,而将原图像像素映射到8位灰度图的映射为线性映射。该映射的斜率为255/窗宽。如果忽略数字类型转换会导致窗宽大于255时图像全为黑的错误,将斜率转换为float类型可以解决此问题。

此外,设置滚动条事件与鼠标讯息回圈函数代码如下:

void change(int,void*) {


	int i = 0;
	int j = 0;
	for(i=0;i<frame.rows;i++)
		for (j = 0; j < frame.cols; j++) {
			show.at<uchar>(i, j) = saturate_cast<uchar>(float(255)/short(width)*(frame.at<short>(i, j)-(level-width/2)));
		}

}
void mouse(int event, int x, int y, int flags,void* userdata){

	switch (event) {
	case(2):level = 400; width = 100;;
		setTrackbarPos("width", "20374230", width);
		setTrackbarPos("level", "20374230", level);
		change(0, 0);
		break;
	}
	switch (flags)
	{case EVENT_FLAG_LBUTTON:
		level= 1500-3*(x - k); width =320-0.5*( y - l);
		setTrackbarPos("width", "20374230", width); 
		setTrackbarPos("level", "20374230", level); 
		change(0,0);
		break;
	default:
		break;
	}
}

鼠标回圈函数利用了滚动条回圈函数。

五、实验过程:

python opencv窗宽窗位 opencv显示窗口调整大小_c++_03

       

六、实验结果:

python opencv窗宽窗位 opencv显示窗口调整大小_1024程序员节_04

        实验开始时打开图像如上图显示,初始窗宽设为100,初始窗位设为400。

python opencv窗宽窗位 opencv显示窗口调整大小_灰度_05

调节窗宽效果如图显示。

python opencv窗宽窗位 opencv显示窗口调整大小_opencv_06

调节窗位效果如图显示。

七、结果分析与实验结论:

        本次实验实现了从short型到float型的像素值映射并逐像素访问修改,实现了鼠标事件以及滚动条事件的窗宽窗位调整。实验效果较好。

源码如下:

#include <iostream>
#include<opencv2\opencv.hpp>
using namespace cv;
using namespace std;
Mat k2;
Mat k1;
int level=400;
int width=100;
Mat frame;	
Mat show;
int k;
int l;
void change(int,void*) {


	int i = 0;
	int j = 0;
	for(i=0;i<frame.rows;i++)
		for (j = 0; j < frame.cols; j++) {
			show.at<uchar>(i, j) = saturate_cast<uchar>(float(255)/short(width)*(frame.at<short>(i, j)-(level-width/2)));
		}

}
void mouse(int event, int x, int y, int flags,void* userdata){

	switch (event) {
	case(2):level = 400; width = 100;;
		setTrackbarPos("width", "20374230", width);
		setTrackbarPos("level", "20374230", level);
		change(0, 0);
		break;
	}
	switch (flags)
	{case EVENT_FLAG_LBUTTON:
		level= 1500-3*(x - k); width =320-0.5*( y - l);
		setTrackbarPos("width", "20374230", width); 
		setTrackbarPos("level", "20374230", level); 
		change(0,0);
		break;
	default:
		break;
	}
}
int main()
{

	double n[] = { 1,2,3,4,1,3,4,5,1 };
	k1=Mat(3, 3, CV_64FC1, n);
	k2 = Mat(3, 3, CV_64FC1,n);
	cout << k1 <<endl<<k2 << endl;
	cout <<k1*k2<<endl; 
	cout<<k1.mul(k2)<<endl;
	cout << determinant(k1 * k2 - k1.mul(k2));
frame = imread("C:\\Users\\pc\\Desktop\\a736ab2b0ab1e8409780f870fa336e0.png", IMREAD_UNCHANGED);//无更改式读取原图
show = Mat::zeros(frame.rows, frame.cols, CV_8UC1);
	namedWindow("20374230");
		createTrackbar("width", "20374230", &width, 255 0,change);
		createTrackbar("level", "20374230", &level, 2000,change);
		setMouseCallback("20374230", mouse);
	while (1) {
	waitKey(100);
	imshow("20374230", show);
	}

}

python opencv窗宽窗位 opencv显示窗口调整大小_c++_07

 实验用图在此,上传网页后可能格式发生更改了,从而其内部像素值全变成了255。