医学软件项目开发(三):骨密度分析QChart创建及ROI相关操作

一.QChart

1.1关键

分段背景色

1.2思路

1.引入QCustomPlot类,官网下载,自定义功能丰富

2.设置线宽(c#中有示例代码)

1.3开发问题

1.在Qt creater测试无问题,在VisualStudio模块未加载进来,在项目右键选择属性->QT Project Settings->Qt Modules 选上Charts

2.文件迁移发生错误,在ui_DicomDisplayWidget中添加QT_CHARTS_USE_NAMESPACES(无效,需改为3)

3.重新编译ui文件会覆盖掉添加的宏定义,在DicomDisplayWidget.h头文件中添加QT_CHARTS_USE_NAMESPACES,且在#include"ui_DicomDisplayWidget.h"前

1.4示例代码

void MainWindow::createChart()
{ 
    //创建图表
    QChartView *chartView=new QChartView(this); //创建 ChartView
    QChart *chart = new QChart(); //创建 Chart
    chart->setTitle("骨密度仪参考:颈(骨密度)");
    chartView->setChart(chart); //Chart添加到ChartView
    this->setCentralWidget(chartView);

//创建曲线序列
    QLineSeries *series0 = new QLineSeries();
    QLineSeries *series1 = new QLineSeries();
    QLineSeries *series2 = new QLineSeries();
    QLineSeries *seriesh0 = new QLineSeries();
    QLineSeries *seriesh1 = new QLineSeries();
    QLineSeries *seriesh2 = new QLineSeries();
    
    //series0->setName("Sin曲线");
    //series1->setName("Cos曲线");
    chart->addSeries(series0); //序列添加到图表
    chart->addSeries(series1);
    chart->addSeries(series2); //序列添加到图表
    chart->addSeries(seriesh0);
    chart->addSeries(seriesh1); //序列添加到图表
    chart->addSeries(seriesh2);
    
    
    chart->addAxis(axisX,Qt::AlignBottom); //坐标轴添加到图表,并指定方向
    chart->addAxis(axisY,Qt::AlignLeft);
    chart->addAxis(axisY,Qt::AlignRight);

    series0->attachAxis(axisX); //序列 series0 附加坐标轴
    series0->attachAxis(axisY);

    series1->attachAxis(axisX);//序列 series1 附加坐标轴
    series1->attachAxis(axisY);

	QPen pen;
	pen.setStyle(Qt::DotLine);//Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine
	pen.setWidth(2);
	pen.setColor(Qt::red);
	series0->setPen(pen);
	pen.setStyle(Qt::SolidLine);//Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine
	pen.setColor(Qt::blue);
	series1->setPen(pen);

//序列添加数值
    qreal t=0,y1,y2,intv=0.1;
    int cnt=100;
    for(int i=0;i<cnt;i++)
    {
        y1=qSin(t);//+qrand();
        series0->append(t,y1);

        y2=qSin(t+20);
        series1->append(t,y2);
        t+=intv;
    }


//    chart->createDefaultAxes();
//    chart->axisX()->setTitleText("time(secs)");
//    chart->axisY()->setTitleText("value");

    
//创建坐标轴
    QValueAxis *axisX = new QValueAxis; //X 轴
    axisX->setRange(20, 100); //设置坐标轴范围
//    axisX->setLabelFormat("%.1f"); //标签格式
//    axisX->setTickCount(11); //主分隔个数
//    axisX->setMinorTickCount(4);
    axisX->setTitleText("年龄(岁)"); //标题
//    axisX->setGridLineVisible(false);

    QValueAxis *axisY1 = new QValueAxis; //Y 轴
    axisY->setRange(0.514, 1.354);
    axisY->setTitleText("BMD(g/cm2)");
//    axisY->setTickCount(5);
//    axisY->setMinorTickCount(4);
    axisY->setLabelFormat("%.2f"); //标签格式
//    axisY->setGridLineVisible(false);

    chart->setAxisX(axisX, series0); //为序列设置坐标轴
    chart->setAxisY(axisY, series0); //

    chart->setAxisX(axisX, series1); //为序列设置坐标轴
    chart->setAxisY(axisY, series1); //
}

1.5项目代码

void DicomDisplayWidget::createChart()
{
	chart->setTitle("骨密度仪参考:颈(骨密度)");
	chart->legend()->hide();//隐藏图标
	ui.spineChart->setChart(chart); //Chart添加到ChartView

	//创建三个LineSeries并添加点
	QLineSeries *series0 = new QLineSeries();
	QLineSeries *series1 = new QLineSeries();
	QLineSeries *series2 = new QLineSeries();
	*series0 << QPointF(0, 0.994) << QPointF(45, 0.994) << QPointF(70, 0.694) << QPointF(100, 0.574);
	*series1 << QPointF(0, 0.994 + 0.12) << QPointF(45, 0.994 + 0.12) << QPointF(70, 0.694 + 0.12) << QPointF(100, 0.574 + 0.12);
	*series2 << QPointF(0, 0.994 + 0.24) << QPointF(45, 0.994 + 0.24) << QPointF(70, 0.694 + 0.24) << QPointF(100, 0.574 + 0.24);

	QPen pen;
	pen.setStyle(Qt::SolidLine);//Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine
	pen.setWidth(2);
	pen.setColor(Qt::black);
	series0->setPen(pen);
	series1->setPen(pen);
	series2->setPen(pen);


	axisX->setRange(20, 100); //设置坐标轴范围
	axisX->setTitleText("年龄(岁)"); //标题
	axisX->setTickCount(9); //主分隔个数
	axisX->setMinorTickCount(1);
	axisX->setGridLineVisible(false);
	axisX->setMinorGridLineVisible(false);


	axisY1->setRange(0.514, 1.354);
	axisY1->setTitleText("BMD(g/cm2)");
	axisY1->setLabelFormat("%.3f"); //标签格式
	axisY1->setTickCount(8); //主分隔个数
	axisY1->setGridLineVisible(false);
	axisY1->setMinorGridLineVisible(false);

	axisY2->setRange(-5, 2);
	axisY2->setTitleText("T值");
	axisY2->setTickCount(8); //主分隔个数
	axisY2->setGridLineVisible(false);
	axisY2->setMinorGridLineVisible(false);

	createBackground();
	//序列添加到图表
	chart->addSeries(series0); 
	chart->addSeries(series1);
	chart->addSeries(series2); 
	//与X轴和Y1轴建立联系
	series0->attachAxis(axisX);
	series0->attachAxis(axisY1);
	series1->attachAxis(axisX);
	series1->attachAxis(axisY1);
	series2->attachAxis(axisX);
	series2->attachAxis(axisY1);
}

void DicomDisplayWidget::createBackground()
{
	QLineSeries *seriesredh0 = new QLineSeries();
	QLineSeries *seriesredh1 = new QLineSeries();//红色区域下上边界线
	QLineSeries *seriesyellowh0 = new QLineSeries();
	QLineSeries *seriesyellowh1 = new QLineSeries();//黄色区域下上边界线
	QLineSeries *seriesgreenh0 = new QLineSeries();
	QLineSeries *seriesgreenh1 = new QLineSeries();//绿色区域下上边界线
	*seriesredh0 << QPointF(20, -5) << QPointF(100, -5);
	*seriesredh1 << QPointF(20, -2.5) << QPointF(100, -2.5);
	*seriesyellowh0 << QPointF(20, -2.5) << QPointF(100, -2.5);
	*seriesyellowh1 << QPointF(20, -1) << QPointF(100, -1);
	*seriesgreenh0 << QPointF(20, -1) << QPointF(100, -1);
	*seriesgreenh1 << QPointF(20, 2) << QPointF(100, 2);
	QAreaSeries *seriesred = new QAreaSeries(seriesredh0, seriesredh1);
	QAreaSeries *seriesyellow = new QAreaSeries(seriesyellowh0, seriesyellowh1);
	QAreaSeries *seriesgreen = new QAreaSeries(seriesgreenh0, seriesgreenh1);
	QPen penred(Qt::red);//设置红色画笔
	QPen penyellow(Qt::yellow);//设置黄色画笔
	QPen pengreen(Qt::green);//设置绿色画笔
	penred.setWidth(2);//画笔宽度
	penyellow.setWidth(2);//画笔宽带
	pengreen.setWidth(2);//画笔宽带
	//series->setPointsVisible(true);//设置点可见
	//series->setPointLabelsVisible(true);//设置点边缘可见
	seriesred->setPen(penred);
	seriesred->setBrush(Qt::red);
	seriesyellow->setPen(penyellow);
	seriesyellow->setBrush(Qt::yellow);
	seriesgreen->setPen(pengreen);
	seriesgreen->setBrush(Qt::green);

	chart->addSeries(seriesred);
	chart->addSeries(seriesyellow);
	chart->addSeries(seriesgreen);

	//坐标轴添加到图表,并指定方向
	chart->addAxis(axisX, Qt::AlignBottom); 
	chart->addAxis(axisY1, Qt::AlignLeft);
	chart->addAxis(axisY2, Qt::AlignRight);

	seriesred->attachAxis(axisX);//与X轴和Y2轴建立联系
	seriesred->attachAxis(axisY2);
	seriesyellow->attachAxis(axisX);//与X轴和Y2轴建立联系
	seriesyellow->attachAxis(axisY2);
	seriesgreen->attachAxis(axisX);//与X轴和Y2轴建立联系
	seriesgreen->attachAxis(axisY2);
}

二、提取分割重要参数

2.1转换QPoint为cv::point并转换QVector为std::vector

void ImageGView::startSpineOutline()
{
	QVector<QPointF> vectorSpineOutline;
	vectorSpineOutline = m_bllSegPoint->spineOutline();//脊柱勾边分割
	addPathItem(QString("SPineOutLine_%1").arg(m_pathNum));
	m_pathItem->setPolygon(vectorSpineOutline);
	QVector<Point> vectorSpineOutlineCv;
	for (int i = 0; i < vectorSpineOutline.size(); i++)
	{
		QPointF qspineoutline = vectorSpineOutline[i];
		Point pspineoutline;
		pspineoutline.x = qspineoutline.x();
		pspineoutline.y = qspineoutline.y();
		vectorSpineOutlineCv.append(pspineoutline);
	}
	std::vector<Point> stdVectorSpineOutlineCv = vectorSpineOutlineCv.toStdVector();
	std::vector<std::vector<Point>> contour;
	contour.push_back(stdVectorSpineOutlineCv);
	Mat roi = Mat::zeros(S_OrgImg.size(), CV_8U);
	Mat dst;
	drawContours(roi, contour, 0, Scalar::all(255), -1);
	S_OrgImg.copyTo(dst, roi);

 }

void ImageGView::startSpineAreaSeg()
{
	QVector<QVector<QPointF> > vectorSpineAreaSeg;
	QVector<Point> vectorSpineAreaCv;
	std::vector<std::vector<Point>> contour;
	vectorSpineAreaSeg = m_bllSegPoint->spineAreaSeg();//脊柱区域分割
	for (int i = 0; i < vectorSpineAreaSeg.size();i++)
	{
		QVector<QPointF> vector = vectorSpineAreaSeg.at(i);
		addPathItem(QString("SPineOutLine_%1").arg(m_pathNum));
		m_pathItem->setPolygon(vector);
		
		for (int j = 0; j < vector.size(); j++)
		{
			QPointF qspinearealine = vector[j];
			Point pspinearealine;
			pspinearealine.x = qspinearealine.x();
			pspinearealine.y = qspinearealine.y();
			vectorSpineAreaCv.append(pspinearealine);
		}
		
		std::vector<Point> stdVectorSpineAreaCv = vectorSpineAreaCv.toStdVector();
		
		contour.push_back(stdVectorSpineAreaCv);
		vectorSpineAreaCv.clear();
	}
	
	
	Mat roi = Mat::zeros(S_OrgImg.size(), CV_8U);
	Mat dst;
	drawContours(roi, contour, 1, Scalar::all(255), -1);
	S_OrgImg.copyTo(dst, roi);

2.2contourArea()函数

//计算轮廓面积
vector<Point> contour;
double contourArea(InputArray contour,bool oriented=faulse)
    //可以为std::vector或Mat类型

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