[Opencv]实验:实现窗宽窗位调节(附源码及解析)

本文档介绍了一个使用OpenCV实现医学图像窗宽窗位调节的实验。通过逐像素访问和修改,结合鼠标事件和滚动条控制,调整8位灰度图像以显示医学图像的特定灰度范围。实验中详细解释了窗宽窗位的概念,并展示了如何通过线性映射将原图像的灰度值映射到0-255的范围内。代码解析部分解释了关键的映射公式以及滚动条和鼠标事件的处理函数。实验结果显示,该方法能够有效地实现窗宽和窗位的动态调节,以适应不同的显示需求。
摘要由CSDN通过智能技术生成

一、摘要

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

二、实验内容:

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

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

三、算法流程:

四、代码解析:

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

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

         代码中的实现如下:

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;
	}
}

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

五、实验过程:

       

六、实验结果:

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

调节窗宽效果如图显示。

调节窗位效果如图显示。

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

        本次实验实现了从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);
	}

}

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

电脑玩家爹爸父

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值