Qt中建菜单栏和工具栏(泊松编辑)

最近在学Qt,以下为学习过程(在VS中运用Qt):

建菜单栏时可以直接在Qt Designer里建,但是之后在建立菜单栏信号和槽连接的时候我不知道怎么弄了,百度了下说是在Designer里面只能使用里面自带的槽。所以我最后用直接写代码的方式建立了菜单栏和工具栏,代码如下:

#include "mainwindow.h"
#include <QAction>
MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);
	openAction = new QAction(tr("&Open"), this); 
	openAction->setShortcut(QKeySequence::Open); 
	QMenu *file = menuBar()->addMenu(tr("&File")); 
	file->addAction(openAction); 

	QToolBar *toolBar = addToolBar(tr("&File")); 
	toolBar->addAction(openAction);
	connect(openAction, SIGNAL(triggered()), this, SLOT(openImage()));
}


之后我想读取图片并显示出来,刚开始只能显示一张,如果再打开一张,前面一张会消失,后来又加了一个读取图片的并改变了图片显示的位置,从而可以连续的打开两张图片。(此处有待学习,待之后学会了再改进),代码如下:

void MainWindow::openImage()
{
	QString filename=QFileDialog::getOpenFileName(this, 
		tr("Open Image"),"", 
		tr("BMP(*.bmp);;JPG(*.jpg);;ALL files(*.*)")); 
	if(filename.isEmpty()) 
	{ 
		QMessageBox::information(this,tr("Open Image"), 
			tr("Please select an image to open")); 
		filename=QFileDialog::getOpenFileName(this, 
			tr("Open Image"),"", 
			tr("BMP(*.bmp);;JPG(*.jpg);;ALL files(*.*)")); 
	} 

	if(!(img1.load(filename,0))) 
	{ 
		QMessageBox::information(this,tr("Unable to open the Image"), 
			tr("Please select a valid image.")); 
		return; 
	} 

	QWidget::update(); 
	QString filename2=QFileDialog::getOpenFileName(this, 
		tr("Open Image"),"", 
		tr("BMP(*.bmp);;JPG(*.jpg);;ALL files(*.*)")); 
	if(filename2.isEmpty()) 
	{ 
		QMessageBox::information(this,tr("Open Image"), 
			tr("Please select an image to open")); 
		filename=QFileDialog::getOpenFileName(this, 
			tr("Open Image"),"", 
			tr("BMP(*.bmp);;JPG(*.jpg);;ALL files(*.*)")); 
	} 

	if(!(img2.load(filename2,0))) 
	{ 
		QMessageBox::information(this,tr("Unable to open the Image"), 
			tr("Please select a valid image.")); 
		return; 
	} 

	QWidget::update(); 
}

我们使用了setShortcut函数。shortcut是这个动作的快捷键。Qt的QKeySequence已经为我们定义了很多内置的快捷键,比如我们使用的Open。你可以通过查阅API文档获得所有的快捷键列表,或者是在QtCreator中输入::后会有系统的自动补全功能显示出来。这个与我们自己定义的有什么区别呢?简单来说,我们完全可以自己定义一个tr("Ctrl+O")来实现快捷键。原因在于,这是Qt跨平台性的体现。比如PC键盘和Mac键盘是不一样的,一些键在PC键盘上有,而Max键盘上可能并不存在,或者反之,所以,推荐使用QKeySequence类来添加快捷键,这样,它会根据平台的不同来定义不同的快捷键。

QMainWindow有一个menuBar()函数,会返回菜单栏,也就是最上面的那一条。如果不存在会自动创建,如果已经存在就返回那个菜单栏的指针。直接使用返回值添加一个菜单,也就是addMenu,参数是一个QString,也就是显示的菜单名字。然后使用这个QMenu指针添加这个QAction。类似的,使用addToolBar函数的返回值添加了一个工具条,并且把这个QAction添加到了上面。

void MainWindow::paintEvent(QPaintEvent *event) 
{ 
	QPainter painter(this); 
	if(!img1.isNull()) 
		painter.drawImage(50,50,img1); 
	if(!img2.isNull()) 
		painter.drawImage(50,250,img2); 
} 


接下来又用双缓冲绘图的方法在窗口中画矩形(选取图片上的某个区域),该方法可以使用鼠标在界面上绘制一个任意大小的矩形。这里需要两张画布,其中一个tempPix用来作为临时缓冲区,当鼠标正在拖动矩形进行绘制时,将内容先绘制到tempPix上,然后将tempPix绘制到界面上;而另一个pix作为缓冲区,用来保存已经完成的绘制。当松开鼠标完成矩形的绘制后,则将tempPix的内容复制到pix上,为了绘制时不显示拖影,那么在移动鼠标的过程中,每绘制一次,都要在刚开始绘制这个矩形的图像上进行绘制,所以需要在每次绘制tempPix之前,先将pix的内容复制到tempPix上。代码如下:


void MainWindow::paintEvent(QPaintEvent *event) 
{ 
	QPainter painter(this); 
	if(!img1.isNull()) 
		painter.drawPixmap(50,50,img1); 
	if(!img2.isNull()) 
		painter.drawPixmap(400,50,img2);

	tempPix=pix;
	isDrawing=false;

	int x=startPoint.x();
	int y=startPoint.y();
	int width=endPoint.x()-x;
	int height=endPoint.y()-y;

	painter.begin(&tempPix);
	QPen pen(Qt::blue,2,Qt::DotLine);
	painter.setPen(pen);
	painter.drawRect(x,y,width,height);
	painter.end();
	painter.begin(this);
	painter.drawPixmap(0,0,tempPix);
	if (!isDrawing)
		pix=tempPix;
} 
void MainWindow::mousePressEvent(QMouseEvent *event)
{
	if (event->button()==Qt::LeftButton)
	{
		startPoint=event->pos();
		isDrawing=true;
	}
}

void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
	if (event->buttons() & Qt::LeftButton)
	{
		endPoint=event->pos();
		tempPix=pix;
		update();
	}
}

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
	if (event->button()==Qt::LeftButton)
	{
		endPoint=event->pos();
		isDrawing=false;
		update();
	}
}

虽然可以画出矩形,但是最好是限定在所显示的图像区域内,后期再改进。

以上我其实是先读取两张图片,然后在其中一张图片上用矩形框选取一部分图像,然后把这部分图像粘贴到另一张另图片,目的达到无缝融合。

我先试着把所选取的这部分图片直接复制粘贴到另一张图像上,然后再试着用泊松融合来处理。直接复制粘贴的这部分代码如下:

void MainWindow::paintEvent(QPaintEvent *event) 
{ 
	if (flag==false)
	{
		QPainter painter(this);   
		if(!img1.isNull())   
			painter.drawImage(0,50,img1);   
		if(!img2.isNull())   
			painter.drawImage(400,50,img2);  

		tempPix=pix;  
		isDrawing=false;  

		int x=startPoint.x();  
		int y=startPoint.y();  
		 width=endPoint.x()-x;  
		 height=endPoint.y()-y;  

		painter.begin(&tempPix);  
		QPen pen(Qt::red,2,Qt::DotLine);  
		painter.setPen(pen);  
		painter.drawRect(x,y,width,height);  
		painter.end();  
		painter.begin(this);  
		painter.drawImage(0,0,tempPix);  
		if (!isDrawing)  
			pix=tempPix; 

		Boundarypoint[0]=x;
		Boundarypoint[1]=y;
		Boundarypoint[2]=width;
		Boundarypoint[3]=height;
	}
	else if (flag==true)
	{
		QPainter painter(this); 
		painter.begin(this);
		QRect rect1 = QRect(0, 50, img1.width(), img1.height());
		painter.drawImage(rect1, img1);
		QRect rect2 = QRect(400,50, img2.width(), img2.height());
		painter.drawImage(rect2, img2);
		painter.end();

		painter.begin(this);
		int newx=startPoint.x();
		int newy=startPoint.y();

		int k=0;
		for (int i=newx-400;i<newx-400+width;i++)
		{
			int m=0;
			for (int j=newy-50;j<newy+height-50;j++)
			{
				QRgb value;
				value=img1.pixel(Boundarypoint[0]+k,Boundarypoint[1]-50+m);
				m++;
				img2.setPixel(i,j,value);
			}
			k++;
		}
		QRect rect = QRect(400, 50, img2.width(), img2.height());
		painter.drawImage(rect, img2);
		painter.end();
	}
	
} 


void MainWindow::copyImage()
{
	flag=true;
}

做了好几天终于把泊松融合用Qt做出来了,简单描述一下:

这里要感谢博主http://blog.csdn.net/hjimce/article/details/45716603,看完这个就会对泊松编辑有更好的理解

按步骤首先是要先求所选区域的梯场,再求背景图片的梯度场,然后求融合图像的梯度场,最后求融合图像的散度(对梯度求导),这些要求解系数矩阵。我用的是MKL来求解泊松方程。

我做的时候就直接求了所选区域内部点的散度,粘贴到背景图中。而原图中所选的区域的边界点是不求的,而用的是边界点在背景图的位置处来求解,把背景图放在边界点方程的右边,前面求的内部点的散度也放在右边,根据那个链接里的拉普拉斯算子来求。方程左边就是该点相邻的内部点取1,和该点取-4,最后求解。因为我是直接求的散度,所以还是有所偏差。

说的不清楚,就是记录一下怕自己忘了。有很多不足的地方待改进。

部分代码如下:(方法比较笨)

void MainWindow::PossionEquation(numc::RowMat<double>& rmt, vector<double>& rhsR, vector<double>& rhsG,vector<double>& rhsB)
{
	int divR,divG,divB;
	k=0;    //标号0,1......
	for (int y1=Boundarypoint[1]-50+1;y1<Boundarypoint[1]-50+height-1;y1++)    //求矩形区内部点的散度
	{
		for (int x1=Boundarypoint[0]+1;x1<Boundarypoint[0]+width-1;x1++)
		{
			QColor color(img1.pixel(x1,y1));
			QColor color1(img1.pixel(x1+1,y1));
			QColor color2(img1.pixel(x1-1,y1));
			QColor color3(img1.pixel(x1,y1+1));
			QColor color4(img1.pixel(x1,y1-1));

			divR=color1.red()+color2.red()+color3.red()+color4.red()-4*color.red();
			rhsB[k]=divR;
			divG=color1.green()+color2.green()+color3.green()+color4.green()-4*color.green();
			rhsG[k]=divG;
			divB=color1.blue()+color2.blue()+color3.blue()+color4.blue()-4*color.blue();
			rhsB[k]=divB;
			k++;
		}
	}

	for(int i=0;i<n;i++)
	{
		if (i==0)
		{
			rmt[0][1]=1;
			rmt[0][width-2]=1;
			QColor Co1(img2.pixel(newx-399,newy-50));
			QColor Co2(img2.pixel(newx-400,newy-49));
			rhsR[i]=rhsB[i]-Co1.red()-Co2.red();
			rhsG[i]=rhsG[i]-Co1.green()-Co2.green();
			rhsB[i]=rhsB[i]-Co1.blue()-Co2.blue();
		}
		else if(i==width-3)
		{
			rmt[i][width-4]=1;
			rmt[i][2*width-5]=1;
			QColor Co1(img2.pixel(newx+width-402,newy-50));
			QColor Co2(img2.pixel(newx+width-401,newy-49));
			rhsR[i]=rhsB[i]-Co1.red()-Co2.red();
			rhsG[i]=rhsG[i]-Co1.green()-Co2.green();
			rhsB[i]=rhsB[i]-Co1.blue()-Co2.blue();
		}
		else if (i==n-width+2)
		{
			rmt[i][n-2*width+4]=1;
			rmt[i][n-width+3]=1;
			QColor Co1(img2.pixel(newx-399,newy+height-51));
			QColor Co2(img2.pixel(newx-400,newy+height-52));
			rhsR[i]=rhsB[i]-Co1.red()-Co2.red();
			rhsG[i]=rhsG[i]-Co1.green()-Co2.green();
			rhsB[i]=rhsB[i]-Co1.blue()-Co2.blue();
		}
		else if (i==n-1)
		{
			rmt[i][n-width+1]=1;
			rmt[i][n-2]=1;
			QColor Co1(img2.pixel(newx+width-401,newy+height-52));
			QColor Co2(img2.pixel(newx+width-402,newy+height-51));
			rhsR[i]=rhsB[i]-Co1.red()-Co2.red();
			rhsG[i]=rhsG[i]-Co1.green()-Co2.green();
			rhsB[i]=rhsB[i]-Co1.blue()-Co2.blue();
		}
		else if (i>0&&i<width-3)
		{
			rmt[i][i-1]=1;
			rmt[i][i+1]=1;
			rmt[i][i+width-2]=1;
			QColor Co(img2.pixel(newx+i-399,newy-50));
			rhsR[i]=rhsB[i]-Co.red();
			rhsG[i]=rhsG[i]-Co.green();
			rhsB[i]=rhsB[i]-Co.blue();
		}
		else if (i%(width-2)==0)
		{
			rmt[i][i-width+2]=1;
			rmt[i][i+1]=1;
			rmt[i][i+width-2]=1;
			QColor Co(img2.pixel(newx-400,newy-49+i/(width-2)));  
			rhsR[i]=rhsB[i]-Co.red();
			rhsG[i]=rhsG[i]-Co.green();
			rhsB[i]=rhsB[i]-Co.blue();
		}
		else if (i>(n-width+2)&&i<n-1)
		{
			rmt[i][i-1]=1;
			rmt[i][i+1]=1;
			rmt[i][i-width+2]=1;
			QColor Co(img2.pixel(newx-399+i-(n-width+2),newy+height-51));
			rhsR[i]=rhsB[i]-Co.red();
			rhsG[i]=rhsG[i]-Co.green();
			rhsB[i]=rhsB[i]-Co.blue();
		}
		else if (i%(width-2)==(width-3))
		{
			rmt[i][i-width+2]=1;
			rmt[i][i-1]=1;
			rmt[i][i+width-2]=1;
			QColor Co(img2.pixel(newx+width-401,newy-49+i/(width-3)));
			rhsR[i]=rhsB[i]-Co.red();
			rhsG[i]=rhsG[i]-Co.green();
			rhsB[i]=rhsB[i]-Co.blue();
		}
		else
		{
			rmt[i][i-width+2]=1;
			rmt[i][i-1]=1;
			rmt[i][i+1]=1;
			rmt[i][i+width-2]=1;
		}
		rmt[i][i]=-4;
	}
}

void MainWindow::PossionSolver()
{
	using namespace numc;
	RowMat<double> rmt(n, n);				//根据内部点像素建立方程

	vector<double> rhsR(n);				//R通道右边值
	vector<double> rhsG(n);				//G通道右边值
	vector<double> rhsB(n);				//B通道右边值


	PossionEquation(rmt,rhsR,rhsG,rhsB);
	
#if TEST
	std::ofstream outfile1;
	outfile1.open("equation.txt");
	for (int i =0; i < n; i ++)
	{
		outfile1 << "Row" << i << std::endl;
		for (int j = 0; j < n; j ++)
		{
			outfile1 << rmt[i][j] << " "; 		
		}
		outfile1 << "\t" << rhsU[i] << " " << rhsV[i] << std::endl;
	}
	outfile1.close();
#endif

	CSRMatrix<double> m;
	CreateCSRMatrixFromRowMap(m,rmt);

	numc::CLeastSquareSpareSolver solver;
	solver.init(m);

	vector<double> resultR(n);
	vector<double> resultG(n);
	vector<double> resultB(n);

	solver.solve(&rhsR.front(), &resultR.front());
	solver.solve(&rhsG.front(), &resultG.front());
	solver.solve(&rhsB.front(), &resultB.front());


#if TEST
	for (int i = 0; i < n ; i++)
	{
		std::cout<<resultU[i]<<" " << resultV[i] << std::endl;
	}
#endif
	for (int q=0;q<n;q++)
	{
		if (resultR[q]>255)
			resultR[q]=255;
		if (resultR[q]<0)
			resultR[q]=0;
		if (resultG[q]>255)
			resultG[q]=255;
		if (resultG[q]<0)
			resultG[q]=0;
		if (resultB[q]>255)
			resultB[q]=255;
		if (resultB[q]<0)
			resultB[q]=0;
	}
	int p=0;
	for (int j=newy-50+1;j<newy-50+height-1;j++)
	{
		for (int i=newx-400+1;i<newx-400+width-1;i++)
		{
			QRgb value=qRgba(resultR[p],resultG[p],resultB[p],255);
			img2.setPixel(i,j,value);
			p++;
		}

	}
}
这里因为图片显示的位置和窗口的位置存在一个相对位置,所以要-400,-50
结果如下:




注:初学,还有很多不懂不明白的地方,还望有大神可以指导改进一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我明白了,下面是回答: 您可以使用QT编写一个泊松分布概率密度的工具软件,以下是实现的步骤: 1. 在QT中创建一个工程,并添加一个主窗口。 2. 在主窗口中添加一个输入框和一个按钮,用于输入参数λ(泊松分布的参数)并计算概率密度。 3. 在按钮的槽函数中,获取输入框中的λ值,并使用泊松分布概率密度函数计算概率密度值。 4. 将计算得到的概率密度值输出到主窗口中的文本框中。 5. 可以添加一些其他的功能,如清除按钮、帮助文档等。 下面是一个简单的实现代码: ``` #include <QMainWindow> #include <QLineEdit> #include <QPushButton> #include <QLabel> #include <QtMath> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { setFixedSize(400, 300); setWindowTitle("泊松分布概率密度计算器"); // 输入框和按钮 QLabel *label = new QLabel("λ:", this); label->move(20, 20); QLineEdit *lineEdit = new QLineEdit(this); lineEdit->move(60, 20); QPushButton *btn = new QPushButton("计算", this); btn->move(240, 20); connect(btn, &QPushButton::clicked, [=]() { // 计算概率密度 double lambda = lineEdit->text().toDouble(); double k = 0; double p = 0; QString str = "k\tP(k)\n"; while (p < 0.9999) { p += qExp(-lambda) * qPow(lambda, k) / qFactorial(k); str += QString("%1\t%2\n").arg(k).arg(p); k++; } str += QString("和为:%1").arg(p); // 输出结果 QLabel *resultLabel = new QLabel(str, this); resultLabel->move(20, 60); resultLabel->setFixedSize(360, 220); resultLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); }); } }; ``` 注意,这只是一个简单的实现,泊松分布概率密度的计算方法可能有多种,可以根据自己的需求进行修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值