医学软件项目开发(二):医学图像的显示及相关操作

一、状态栏标签信息

//参考用
QString status = QString("%1, %2x%3, %4 Bytes").arg(path).arg(image.width())
.arg(image.height()).arg(QFile(path).size());
mainStatusLabel->setText(status);

labViewCord=new QLabel("View 坐标:");
labViewCord->setMinimumWidth(150);
ui->statusBar->addWidget(labViewCord);

labViewCord->setText(QString::asprintf("View 坐标:%d,%d",point.x(),point.y()));
QPointF pointScene=ui->View->mapToScene(point); //转换到Scene坐标
labSceneCord->setText(QString::asprintf("Scene 坐标:%.0f,%.0f", pointScene.x(),pointScene.y()));

QPointF pointScene=ui->View->mapToScene(point); //转换到Scene坐标
QGraphicsItem  *item=NULL;
item=scene->itemAt(pointScene,ui->View->transform()); //获取光标下的绘图项
if (item != NULL) //有绘图项
{
    QPointF pointItem=item->mapFromScene(pointScene); //转换为绘图项的局部坐标
    labItemCord->setText(QString::asprintf("Item 坐标:%.0f,%.0f",,pointItem.x(),pointItem.y()));
}
//最初加在QGraphicsView中,但由于图像遮挡并未实施
m_label = new QLabel(this);//关键参数框
m_label->setStyleSheet("QLabel{color:rgba(66, 133, 245, 255);}");//设置字体颜色
m_label->setText(QString::asprintf("patienet name:%s,patient sex:%s \nScene:%.0f,%.0f \nwindowCenter:%d,windowWidth:%d \nHu:%d,pixel:%d", "a", "b", itemPos.x(), itemPos.y(), m_center, m_width, Hu, pixel));

二、信号与槽传递时,clicked后不要遗留括号(Qt4写法)

三、QGraphicsScene与QGraphicsView

先加和后加是有区别的,QGraphicsScene中添加东西时,如addLine,adddItem,后加遮挡前加

设置QGraphicsView的Alignment属相控制场景在视图中的显示位置

QGraphicsItem::pos()返回的是图形项在场景中的坐标

scene->setSceneRect(-5000,-5000,10000,10000);
scene->update(scene->SceneRect());
QRectF pixmapRect=pixmapItem->boundingRect();
QRectF viewRect = this->rect();

setMouseTracking(true)是追踪鼠标的关键,只有这样鼠标移动时,示数才会更新

scene会自动更新,不用添加update

获取正确的qraphicsview的height,需重写Show事件,但可合并到resize事件

QPointF不必转为QPoint,获取Item坐标时转化会出错

Opencv中 img.at为先y后x

ui.DicomDisplayWidget,ui.imageGview ,提升的类,需连续传信号

设置scene时(-200.-100,400,200),不要遗漏负号

看清添加的对象是新创建的对象

四、窗宽窗位调整

Mat lookUpTable(1, 256, CV_8U);//构造查找表时,数字代表1行256列
uchar* p = lookUpTable.data;
for( int i = 0; i < 256; ++i)
p[i] = table[i];
//    然后我们调用函数 (I 是输入 J 是输出):
LUT(I, lookUpTable, J);

通过滑块测试窗宽窗位算法时,窗位调整变化连贯,但窗宽调整会出现白点

ezDicom中测试,发现窗宽都为偶数,于是将窗宽的值设为整数发现滑块可改步长,并更改最大最小值,但实际测试,仍有问题

解决办法:i>bottom & i < top改为i >= bottom & i <= top,情况解决

并且调整鼠标偏差值确定为当前值与先前值之差后,窗宽窗位调整可以任意调节并恢复原来的模样

//提前设置好m_center与m_width
void ImageGView::setWindow(int center, int width)
{
	if (!S_OrgImg.data)
	{
		return;
	}

	Mat temp = S_OrgImg.clone();
	Mat lookUpTable(1, 256, CV_8U);//颜色查找表
	uchar* p = lookUpTable.data;

	int bottom = m_center - m_width / 2;
	int top = m_center + m_width / 2;
	for (int i = 0; i < 256; ++i)
	{
		if (i < bottom)
		{
			p[i] = 0;
		}
		else if (i >= bottom & i <= top)
		{
			p[i] = (i - bottom)* 1.0 * 255 / (top - bottom);
		}
		else
		{
			p[i] = 255;
		}
	}
	cv::LUT(temp, lookUpTable, S_WinImg);//映射
	S_WinImg.copyTo(S_ResImg);
}

void ImageGView::setWinTag(bool enable)
{
	m_winWidthTag = enable;
	m_drawAreaTag = false;
	m_drawPathTag = false;
}

void ImageGView::resetWindow()
{
	m_center = 128;
	m_width = 256;
	setWindow(m_center, m_width);
	updateView();
}
//待测试,16位用参考
void MatGet::setWindowsRange(int bottom, int top)
{
	int a = S_OrgImg.elemSize();
	int size = S_OrgImg.total() * S_OrgImg.elemSize();
	WORD *pCur;
	WORD *pEnd;
	WORD *pImgPro = new WORD[size];
	//int S_ImgSize = MatGet::S_ImgSize;
	std::memcpy(pCur, S_OrgImg.data, size* 8);
	int LUT[2^8];
	
	//生成查找表
	for (int g = 0; g < 2 ^ 8; g++)
	{
		if (g < bottom)
		{
			LUT[g] = 0;
		}
		else if (g > bottom & g < top)
		{
			LUT[g] = (g - bottom)* 1.0 * 255 / (top - bottom);
		}
		else
		{
			LUT[g] = 255;
		}

	}
	for (pCur = pImgPro,pEnd = pCur + size; pCur < pEnd;)
	{
		*(pCur++) = LUT[*pCur];
	}
	Mat result(S_OrgImg.rows, S_OrgImg.cols, CV_8UC3, pImgPro);
	S_OrgImg = result;
	delete pImgPro;
	return;
}

五、放大缩小

5.1窗口放大,图像比例居中

由于原来自适应重写了resizeEvent事件,将此事件删除即可

this->fitInView(m_pixmapItem->boundingRect(), Qt::KeepAspectRatioByExpanding);//自适应大小

5.2放大缩小右键

if (event->buttons()&Qt::RightButton)
	{
		curMousePos = event->pos();
		QPointF delta = curMousePos - prevMousePos;
		double a = delta.y()*0.1;
		double b = qPow(1.0015, a);
		this->scale(b, b);
		this->centerOn(m_pixmapItem);//以图像为中心放大缩小
}

5.3状态栏放大缩小

void ImageGView::zoomIn()
{
	this->scale(0.8, 0.8);
}

void ImageGView::zoomOut()
{
	this->scale(1.2, 1.2);
}

void ImageGView::zoomFit()
{

	this->resetTransform();
}

//位置归位
void ImageGView::posFit()
{
	QRectF rectf = m_scene->sceneRect();
	rectf.moveTo(0, 0);
	m_scene->setSceneRect(rectf);
}

六、QLabel显示图片

pixmap.load("D:\\hipBMD.png");
ui.hipLabel->setPixmap(m_hippixmap);
ui->label->setPixmap(pixmap.scaled(ui->label->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
ui->label->setPixmap(pixmap.scaled(ui->label->width()-5,ui->label->height()-5,Qt::KeepAspectRatio,Qt::SmoothTransformation));
//项目使用
void ProcessConfigWidget::resLabelShow()
{
	QImage q_img(S_ResImg.data, S_ResImg.cols, S_ResImg.rows, S_ResImg.step, QImage::Format_Indexed8);
	QPixmap pixmap = QPixmap::fromImage(q_img);
	ui.resLabel->setPixmap(pixmap.scaled(ui.resLabel->width() - 5, ui.resLabel->height() - 5, Qt::KeepAspectRatio, Qt::SmoothTransformation));
}

显示图片要注意图片后缀为jpg或者为其他格式,不是任意一张图片都为png

if(!image.data)
{
    return}

七、创建静态函数

//头文件
public:
	DataFactory(QWidget *parent = 0);
	~DataFactory();
	static Mat S_OrgImg;//原始数据
	static Mat S_WinImg;//窗宽窗位数据
	static Mat S_ResImg;//处理后数据
	static QString S_PatientInformation;//病人信息
	QString FindDicomTag(const std::string & entryId, const itk::GDCMImageIO::Pointer dicomIO);
	void readDicoms(fileNamesContainer filenamesOut);
//初始化
Mat DataFactory::S_OrgImg;
Mat DataFactory::S_ResImg;
Mat DataFactory::S_WinImg;
QString DataFactory::S_PatientInformation;//病人信息
//别处调用
S_OrgImg = DataFactory::S_OrgImg;
S_WinImg = DataFactory::S_WinImg;
S_ResImg = DataFactory::S_ResImg;
S_PatientInformation = DataFactory::S_PatientInformation;
//静态函数中,有时clone无效,只能用copyTo
S_ResImg=S_OrgImg.clone();
S_WinImg.copyTo(S_ResImg);

你可能感兴趣的:(医学软件开发,ui,qt,visual,studio)