2015-08-11 09:34:11 jolin678 阅读数 5558
  • OpenSceneGraph与qt结合视频教程

    Qt中嵌入OSG控件教程,教大家.认识并简单的应用qt,达到可以做一些自己的小例子;qt与osg是如何传递消息的,如何进行通信;了解三维是如何显示在里。有问题咨询老师微信,微信号:mikeshizhanbiao

    22755 人正在学习 去看看 师占标
作为图像处理的入门,会文件操作,能顺利得到图像的像素就足够了。但是在这方面做出成就就很难了,因为它涉及了很多算法,要做的出众就要有一定的创新就很难了。像海康这样做安防的,在视频方面做得之所以出众,就是因为他们在图像处理、画面处理方面的算法都有自己的创新。
   下面是这段时间,我关于图像处理方面的一些入门算法的实现代码,使用qt实现的,为自己后期实现图像处理(如:图像变形、分割等)做准备,代码分享如下:
 

点击(此处)折叠或打开

  1. #include \"mainwindow.h\"
  2. #include \"ui_mainwindow.h\"
  3. #include <QFileDialog>
  4. #include <QMovie>
  5. #include <QRgb>
  6. #include <math.h>
  7. #include <QInputDialog>
  8. #include <QDebug>
  9. #include <QDialog>
  10. #include <QDoubleSpinBox>
  11. #include <QSpinBox>
  12. #include <QLabel>

  13. MainWindow::MainWindow(QWidget *parent) :
  14.     QMainWindow(parent),
  15.     ui(new Ui::MainWindow)
  16. {
  17.     ui->setupUi(this);
  18.     QMenu *editMenu=ui->menuBar->addMenu(QObject::tr(\"图片(&P)\"));
  19.     QAction *action_Open=editMenu->addAction(QObject::tr(\"打开图片&O\"));
  20.     QMenu *editMenuMake=ui->menuBar->addMenu(QObject::tr(\"图像几何变换(&M)\"));
  21.     QAction *action_Make1=editMenuMake->addAction(QObject::tr(\"图像平移(&T)\"));
  22.     QAction *action_Make2=editMenuMake->addAction(QObject::tr(\"图像放缩(&S)\"));
  23.     QMenu *editMenuBetter=ui->menuBar->addMenu(QObject::tr(\"图像增强(&B)\"));
  24.     QAction *action_Better1=editMenuBetter->addAction(QObject::tr(\"图像锐化(&E)\"));
  25.     QAction *action_Better2=editMenuBetter->addAction(QObject::tr(\"直方图均衡化(&A)\"));
  26.     QAction *action_Better3=editMenuBetter->addAction(QObject::tr(\"消除噪声(&D)\"));
  27.     QMenu *editMenuTiqu=ui->menuBar->addMenu(QObject::tr(\"提取(&G)\"));
  28.     QAction *action_Gray=editMenuTiqu->addAction(QObject::tr(\"图像灰度化\"));
  29.     QAction *action_Get1=editMenuTiqu->addAction(QObject::tr(\"Sobel算子提取\"));
  30.     action_Open->setCheckable(true);
  31.     action_Make1->setCheckable(true);
  32.     action_Make2->setCheckable(true);
  33.     action_Better1->setCheckable(true);
  34.     action_Better2->setCheckable(true);
  35.     action_Better3->setCheckable(true);
  36.     action_Gray->setCheckable(true);
  37.     action_Get1->setCheckable(true);
  38.     connect(action_Open,SIGNAL(triggered()),this,SLOT(OpenPicture()));
  39.     connect(action_Make1,SIGNAL(triggered()),this,SLOT(SetChangeValue()));
  40.     connect(action_Make2,SIGNAL(triggered()),this,SLOT(SetSouValue()));
  41.     connect(action_Better1,SIGNAL(triggered()),this,SLOT(SetBetterValue()));
  42.     connect(action_Better2,SIGNAL(triggered()),this,SLOT(MakePicAverage()));
  43.     connect(action_Gray,SIGNAL(triggered()),this,SLOT(RgbToGray()));
  44.     connect(action_Get1,SIGNAL(triggered()),this,SLOT(SobelGet()));
  45.     connect(action_Better3,SIGNAL(triggered()),this,SLOT(SelectYanKind()));
  46. }

  47. MainWindow::~MainWindow()
  48. {
  49.     delete ui;
  50. }

  51. //获取要处理的图像并显示出来
  52. void MainWindow::OpenPicture()
  53. {
  54.     fileName=QFileDialog::getOpenFileName( this,tr(\"打开文件\"),\"/usr/local/Trolltech\",
  55.                                                    tr(\"任何文件(*.*)\"\";;文本文件(*.txt)\"\";;XML文件(*.xml)\"\";;Images (*.png *.xpm *.jpg)\"));
  56.     QMovie *move=new QMovie(fileName);
  57.     ui->label->move(50,100);
  58.     ui->label->setMovie(move);
  59.     move->start();
  60. }

  61. //确定图像左右、上下的平移量,并触发平移函数
  62. void MainWindow::SetChangeValue()
  63. {
  64.     dialog=new QDialog(this);
  65.     QLabel *WidthLabel=new QLabel(dialog);
  66.     WidthLabel->move(30,50);
  67.     WidthLabel->setText(tr(\"设置宽度的平移量\"));
  68.     setWidthChange=new QSpinBox(dialog);
  69.     setWidthChange->setMaximum(20);
  70.     setWidthChange->setMinimum(-20);
  71.     setWidthChange->move(180,50);
  72.     QLabel *HeightLabel=new QLabel(dialog);
  73.     HeightLabel->move(30,80);
  74.     HeightLabel->setText(tr(\"设置高度的平移量\"));
  75.     setHeightChange=new QSpinBox(dialog);
  76.     setHeightChange->setMaximum(20);
  77.     setHeightChange->setMinimum(-20);
  78.     setHeightChange->move(180,80);
  79.     QPushButton *button=new QPushButton(dialog);
  80.     button->move(180,120);
  81.     button->setText(tr(\"确定\"));
  82.     dialog->show();
  83.     connect(button,SIGNAL(clicked()),this,SLOT(ShowChangePic()));
  84. }
  85. //平移函数
  86. void MainWindow::ShowChangePic()
  87. {

  88.     image=new QImage(fileName);
  89.     QImage ChangeImage;
  90.     ChangeImage=QImage(image->width(),image->height(),QImage::Format_ARGB32);
  91.     QRgb rgb;
  92.     int width,height;
  93.     int i,j;
  94.     int widthOffset,heightOffset;
  95.     width=image->width();
  96.     height=image->height();
  97.     widthOffset=setWidthChange->value();
  98.     heightOffset=setHeightChange->value();
  99.     for(i=0;i<width;i++)
  100.     {
  101.         for(j=0;j<height;j++)
  102.         {
  103.             rgb=image->pixel(i,j);
  104.             if(ChangeImage.valid(i+widthOffset,j+heightOffset))
  105.             {
  106.                 ChangeImage.setPixel(i+widthOffset,j+heightOffset,rgb);
  107.             }
  108.         }
  109.      }
  110.      ui->label_2->resize(ChangeImage.width(),ChangeImage.height());
  111.      ui->label_2->setPixmap(QPixmap::fromImage(ChangeImage));
  112.      delete image;
  113.      delete dialog;
  114. }

  115. //设置图像伸缩的比例并触发伸缩函数
  116. void MainWindow::SetSouValue()
  117. {
  118.     dialog=new QDialog(this);
  119.     QLabel *WidthLabel=new QLabel(dialog);
  120.     WidthLabel->move(30,50);
  121.     WidthLabel->setText(tr(\"设置宽度的缩放比例\"));
  122.     setWidthBi=new QDoubleSpinBox(dialog);
  123.     setWidthBi->setMaximum(20);
  124.     setWidthBi->setMinimum(0.1);
  125.     setWidthBi->move(180,50);
  126.     QLabel *HeightLabel=new QLabel(dialog);
  127.     HeightLabel->move(30,80);
  128.     HeightLabel->setText(tr(\"设置高度的缩放比例\"));
  129.     setHeightBi=new QDoubleSpinBox(dialog);
  130.     setHeightBi->setMaximum(20);
  131.     setHeightBi->setMinimum(0.1);
  132.     setHeightBi->move(180,80);
  133.     QPushButton *button=new QPushButton(dialog);
  134.     button->move(180,120);
  135.     button->setText(tr(\"确定\"));
  136.     dialog->show();
  137.     connect(button,SIGNAL(clicked()),this,SLOT(ShowSouPic()));
  138. }
  139. //伸缩函数
  140. void MainWindow::ShowSouPic()
  141. {
  142.     int width,height;
  143.     image=new QImage(fileName);
  144.     width=image->width();
  145.     height=image->height();
  146.     double x,y,r1,r2,g1,g2,b1,b2;
  147.     int i,j;
  148.     double width_bi,height_bi;
  149.     QRgb rgb00,rgb01,rgb10,rgb11;
  150.     int r,g,b;
  151.     QImage SouImage;
  152.     width_bi=setWidthBi->value();
  153.     height_bi=setHeightBi->value();
  154.     SouImage=QImage(width*width_bi,height*height_bi,QImage::Format_ARGB32);
  155.     for(i=0;i<width*width_bi;i++)
  156.     {
  157.         for(j=0;j<height*height_bi;j++)
  158.         {
  159.             x=i*(1/width_bi);
  160.             y=j*(1/height_bi);

  161.             //边界采用单线性插值
  162.             if(ceil(x)==0&&ceil(y)!=0)
  163.             {
  164.                 rgb00=image->pixel(0,ceil(y)-1);
  165.                 rgb01=image->pixel(0,ceil(y));
  166.                 r=(ceil(y)-y)*qRed(rgb00)+(y-(ceil(y)-1))*qRed(rgb01);
  167.                 g=(ceil(y)-y)*qGreen(rgb00)+(y-(ceil(y)-1))*qGreen(rgb01);
  168.                 b=(ceil(y)-y)*qBlue(rgb00)+(y-(ceil(y)-1))*qBlue(rgb01);
  169.                 SouImage.setPixel(i,j,qRgb(r,g,b));
  170.             }

  171.             if(ceil(y)==0&&ceil(y)!=0)
  172.             {
  173.                 rgb00=image->pixel(ceil(x)-1,0);
  174.                 rgb10=image->pixel(ceil(x),0);
  175.                 r=(ceil(x)-x)*qRed(rgb00)+(x-(ceil(x)-1))*qRed(rgb10);
  176.                 g=(ceil(x)-x)*qGreen(rgb00)+(x-(ceil(x)-1))*qGreen(rgb10);
  177.                 b=(ceil(x)-x)*qBlue(rgb00)+(x-(ceil(x)-1))*qBlue(rgb10);
  178.                 SouImage.setPixel(i,j,qRgb(r,g,b));
  179.             }

  180.             //(0,0)点特殊处理
  181.             if(ceil(y)==0&&ceil(y)==0)
  182.             {
  183.                 rgb00=image->pixel(0,0);
  184.                 SouImage.setPixel(i,j,rgb00);
  185.             }

  186.             //非边界采用双线性插值
  187.             if(ceil(x)!=0&&ceil(y)!=0)
  188.             {
  189.                 rgb00=image->pixel(ceil(x)-1,ceil(y)-1);
  190.                 rgb01=image->pixel(ceil(x)-1,ceil(y));
  191.                 rgb10=image->pixel(ceil(x),ceil(y)-1);
  192.                 rgb11=image->pixel(ceil(x),ceil(y));

  193.                 r1=(ceil(x)-x)*qRed(rgb00)+(x-(ceil(x)-1))*qRed(rgb10);
  194.                 r2=(ceil(x)-x)*qRed(rgb01)+(x-(ceil(x)-1))*qRed(rgb11);
  195.                 r=(int)((ceil(y)-y)*r1+(y-(ceil(y)-1))*r2);

  196.                 g1=(ceil(x)-x)*qGreen(rgb00)+(x-(ceil(x)-1))*qGreen(rgb10);
  197.                 g2=(ceil(x)-x)*qGreen(rgb01)+(x-(ceil(x)-1))*qGreen(rgb11);
  198.                 g=(int)((ceil(y)-y)*g1+(y-(ceil(y)-1))*g2);

  199.                 b1=(ceil(x)-x)*qBlue(rgb00)+(x-(ceil(x)-1))*qBlue(rgb10);
  200.                 b2=(ceil(x)-x)*qBlue(rgb01)+(x-(ceil(x)-1))*qBlue(rgb11);
  201.                 b=(int)((ceil(y)-y)*b1+(y-(ceil(y)-1))*b2);

  202.                 SouImage.setPixel(i,j,qRgb(r,g,b));
  203.             }
  204.         }
  205.     }
  206.     ui->label_2->resize(SouImage.width(),SouImage.height());
  207.     ui->label_2->setPixmap(QPixmap::fromImage(SouImage));
  208.     delete image;
  209.     delete dialog;
  210. }

  211. //设置图像锐化的阈值并触发图像锐化函数
  212. void MainWindow::SetBetterValue()
  213. {
  214.     dialog=new QDialog(this);
  215.     QLabel *WidthLabel=new QLabel(dialog);
  216.     WidthLabel->move(30,50);
  217.     WidthLabel->setText(tr(\"设置锐化的阈值\"));
  218.     setBetterValue=new QSpinBox(dialog);
  219.     setBetterValue->setMaximum(100);
  220.     setBetterValue->setMinimum(10);
  221.     setBetterValue->move(180,50);
  222.     QPushButton *button=new QPushButton(dialog);
  223.     button->move(180,70);
  224.     button->setText(tr(\"确定\"));
  225.     dialog->show();
  226.     connect(button,SIGNAL(clicked()),this,SLOT(MakePicBetter()));
  227. }
  228. //图像锐化
  229. void MainWindow::MakePicBetter()
  230. {
  231.     image=new QImage(fileName);
  232.     QImage ImageBetter;
  233.     ImageBetter=QImage(image->width(),image->height(),QImage::Format_ARGB32);
  234.     int i,j;
  235.     int r,g,b,tmpR,tmpG,tmpB;
  236.     QRgb rgb00,rgb01,rgb10;
  237.     int width=image->width(),height=image->height();
  238.     int betterValue=setBetterValue->value();
  239.     for(i=0;i<width;i++)
  240.     {
  241.         for(j=0;j<height;j++)
  242.         {
  243.             if(image->valid(i,j)&&image->valid(i+1,j)&&image->valid(i,j+1))
  244.             {
  245.                 rgb00=image->pixel(i,j);
  246.                 rgb01=image->pixel(i,j+1);
  247.                 rgb10=image->pixel(i+1,j);
  248.                 r=qRed(rgb00);
  249.                 g=qGreen(rgb00);
  250.                 b=qBlue(rgb00);
  251.                 tmpR=abs(qRed(rgb00)-qRed(rgb01))+abs(qRed(rgb00)-qRed(rgb10));
  252.                 tmpG=abs(qGreen(rgb00)-qGreen(rgb01))+abs(qGreen(rgb00)-qGreen(rgb10));
  253.                 tmpB=abs(qBlue(rgb00)-qBlue(rgb01))+abs(qBlue(rgb00)-qBlue(rgb10));
  254.                 if((tmpR+120)<255)
  255.                 {
  256.                     if(tmpR>betterValue)
  257.                     {
  258.                         r=tmpR+120;
  259.                     }
  260.                 }
  261.                 else
  262.                 {
  263.                     r=255;
  264.                 }

  265.                 if((tmpG+120)<255)
  266.                 {
  267.                     if(tmpG>betterValue)
  268.                     {
  269.                         g=tmpG+120;
  270.                     }
  271.                 }
  272.                 else
  273.                 {
  274.                     g=255;
  275.                 }

  276.                 if((tmpB+120)<255)
  277.                 {
  278.                     if(tmpB>betterValue)
  279.                     {
  280.                         b=tmpB+120;
  281.                     }
  282.                 }
  283.                 else
  284.                 {
  285.                     b=255;
  286.                 }
  287.                 ImageBetter.setPixel(i,j,qRgb(r,g,b));
  288.         }
  289.         }
  290.     }
  291.     ui->label_2->resize(ImageBetter.width(),ImageBetter.height());
  292.     ui->label_2->setPixmap(QPixmap::fromImage(ImageBetter));
  293.     delete image;
  294.     delete dialog;
  295. }
  296. //图像的直方图均衡化
  297. void MainWindow::MakePicAverage()
  298. {
  299.     image=new QImage(fileName);
  300.     QImage ImageAverage;
  301.     ImageAverage=QImage(image->width(),image->height(),QImage::Format_ARGB32);
  302.     int i,j;
  303.     int width,height;
  304.     width=image->width();
  305.     height=image->height();
  306.     QRgb rgb;
  307.     int r[256],g[256],b[256];//原图各个灰度数量的统计
  308.     int rtmp,gtmp,btmp,rj,gj,bj;
  309.     float rPro[256],gPro[256],bPro[256];//原图各个灰度级的概率
  310.     float rTemp[256],gTemp[256],bTemp[256];//均衡化后各个灰度级的概率
  311.     int rJun[256],gJun[256],bJun[256];//均衡化后对应像素的值
  312.     memset(r,0,sizeof(r));
  313.     memset(g,0,sizeof(g));
  314.     memset(b,0,sizeof(b));

  315.     //获取原图各个灰度的数量
  316.     for(i=0;i<width;i++)
  317.     {
  318.         for(j=0;j<height;j++)
  319.         {
  320.             rgb=image->pixel(i,j);
  321.             r[qRed(rgb)]++;
  322.             g[qGreen(rgb)]++;
  323.             b[qBlue(rgb)]++;
  324.         }
  325.     }

  326.     //获取原图各个灰度级的概率
  327.     for(i=0;i<256;i++)
  328.     {
  329.         rPro[i]=(r[i]*1.0)/(width*height);
  330.         gPro[i]=(g[i]*1.0)/(width*height);
  331.         bPro[i]=(b[i]*1.0)/(width*height);
  332.     }

  333.     //均衡化后各个灰度级的概率,同时获取均衡化后对应像素的值
  334.     for(i=0;i<256;i++)
  335.     {
  336.         if(i==0)
  337.         {
  338.             rTemp[0]=rPro[0];
  339.             gTemp[0]=gPro[0];
  340.             bTemp[0]=bPro[0];
  341.         }
  342.         else
  343.         {
  344.             rTemp[i]=rTemp[i-1]+rPro[i];
  345.             gTemp[i]=gTemp[i-1]+gPro[i];
  346.             bTemp[i]=bTemp[i-1]+bPro[i];
  347.         }
  348.         rJun[i]=(int)(255*rTemp[i]+0.5);
  349.         gJun[i]=(int)(255*gTemp[i]+0.5);
  350.         bJun[i]=(int)(255*bTemp[i]+0.5);
  351.     }

  352.     for(i=0;i<width;i++)
  353.     {
  354.         for(j=0;j<height;j++)
  355.         {
  356.             rgb=image->pixel(i,j);
  357.             rtmp=qRed(rgb);
  358.             gtmp=qGreen(rgb);
  359.             btmp=qBlue(rgb);
  360.             rj=rJun[rtmp];
  361.             gj=gJun[gtmp];
  362.             bj=bJun[btmp];
  363.             ImageAverage.setPixel(i,j,qRgb(rj,gj,bj));
  364.         }
  365.     }
  366.     ui->label_2->resize(ImageAverage.width(),ImageAverage.height());
  367.     ui->label_2->setPixmap(QPixmap::fromImage(ImageAverage));
  368.     delete image;
  369. }

  370. //Sobel算子提取图像边界
  371. void MainWindow::SobelGet()
  372. {
  373.     image=new QImage(fileName);
  374.     QImage SobelIma;
  375.     SobelIma=QImage(image->width(),image->height(),QImage::Format_ARGB32);
  376.     Template(SobelIma);
  377.     ui->label_2->resize(SobelIma.width(),SobelIma.height());
  378.     ui->label_2->setPixmap(QPixmap::fromImage(SobelIma));
  379. }
  380. //与算子进行卷积的函数
  381. void MainWindow::Template(QImage &SobelImage)
  382. {
  383.     int width=image->width(),height=image->height();
  384.     int pixelNum=width*height;
  385.     int i,j,k,l;
  386.     float rResult,gResult,bResult;
  387.     float sobel1[9]={1,2,1,0,0,0,-1,-2,-1},sobel2[9]={1,0,-1,2,0,-2,1,0,-1};
  388.     QRgb pixelOld[pixelNum],pixelTemp1[pixelNum],pixelTemp2[pixelNum];
  389.     int rtmp,gtmp,btmp;
  390.     memset(pixelTemp1,255,pixelNum);
  391.     memset(pixelTemp2,255,pixelNum);
  392.     QRgb tmpRgb;
  393.     for(j=0;j<height;j++)
  394.     {
  395.         for(i=0;i<width;i++)
  396.         {
  397.             tmpRgb=image->pixel(i,j);
  398.             pixelOld[j*width+i]=tmpRgb;
  399.         }
  400.     }
  401.     for(j=1;j<height-1;j++)
  402.     {
  403.         for(i=1;i<width-1;i++)
  404.         {
  405.             rResult=0;
  406.             gResult=0;
  407.             bResult=0;
  408.             for(k=0;k<3;k++)
  409.             {
  410.                 for(l=0;l<3;l++)
  411.                 {
  412.                     rResult+=qRed(pixelOld[(j-1+k)*width+(i-1+l)])*sobel1[k*3+l];
  413.                     gResult+=qGreen(pixelOld[(j-1+k)*width+(i-1+l)])*sobel1[k*3+l];
  414.                     bResult+=qBlue(pixelOld[(j-1+k)*width+(i-1+l)])*sobel1[k*3+l];
  415.                 }
  416.             }
  417.             rResult=(float)fabs(rResult);
  418.             gResult=(float)fabs(gResult);
  419.             bResult=(float)fabs(bResult);
  420.             if(rResult>255)
  421.             {
  422.                 rtmp=255;
  423.             }
  424.             else
  425.                 rtmp=(int)(rResult+0.5);
  426.             if(gResult>255)
  427.                 gtmp=255;
  428.             else
  429.                 gtmp=(int)(gResult+0.5);
  430.             if(bResult>255)
  431.                 btmp=255;
  432.             else
  433.                 btmp=(int)(bResult+0.5);
  434.             pixelTemp1[j*width+i]=qRgb(rtmp,gtmp,btmp);
  435.         }
  436.     }

  437.     for(j=1;j<height-1;j++)
  438.     {
  439.         for(i=1;i<width-1;i++)
  440.         {
  441.             rResult=0;
  442.             gResult=0;
  443.             bResult=0;
  444.             for(k=0;k<3;k++)
  445.             {
  446.                 for(l=0;l<3;l++)
  447.                 {
  448.                     rResult+=qRed(pixelOld[(j-1+k)*width+(i-1+l)])*sobel2[k*3+l];
  449.                     gResult+=qGreen(pixelOld[(j-1+k)*width+(i-1+l)])*sobel2[k*3+l];
  450.                     bResult+=qBlue(pixelOld[(j-1+k)*width+(i-1+l)])*sobel2[k*3+l];
  451.                 }
  452.             }
  453.             rResult=(float)fabs(rResult);
  454.             gResult=(float)fabs(gResult);
  455.             bResult=(float)fabs(bResult);
  456.             if(rResult>255)
  457.                 rtmp=255;
  458.             else
  459.                 rtmp=(int)(rResult+0.5);
  460.             if(gResult>255)
  461.                 gtmp=255;
  462.             else
  463.                 gtmp=(int)(gResult+0.5);
  464.             if(bResult>255)
  465.                 btmp=255;
  466.             else
  467.                 btmp=(int)(bResult+0.5);
  468.             pixelTemp2[j*width+i]=qRgb(rtmp,gtmp,btmp);
  469.         }
  470.     }

  471.     for(i=0;i<pixelNum;i++)
  472.     {
  473.         if(pixelTemp2[i]>pixelTemp1[i])
  474.             pixelTemp1[i]=pixelTemp2[i];
  475.     }
  476.     for(j=0;j<height;j++)
  477.     {
  478.         for(i=0;i<width;i++)
  479.         {
  480.             SobelImage.setPixel(i,j,pixelTemp1[j*width+i]);
  481.         }
  482.     }
  483.     delete[] pixelTemp1;
  484.     delete[] pixelTemp2;
  485.     delete image;
  486. }

  487. //设置图像平滑的方法
  488. void MainWindow::SelectYanKind()
  489. {
  490.     dialog=new QDialog(this);
  491.     QLabel *Label=new QLabel(dialog);
  492.     Label->move(45,20);
  493.     Label->setText(tr(\"设置图像平滑的方法\"));
  494.     QLabel *DescLabel=new QLabel(dialog);
  495.     DescLabel->move(60,45);
  496.     DescLabel->setText(tr(\" 1--邻域平均法\\n 2--加权平均法\\n 3--选择式掩膜平滑\\n\"));
  497.     setKind=new QSpinBox(dialog);
  498.     setKind->setMaximum(3);
  499.     setKind->setMinimum(1);
  500.     setKind->move(65,100);
  501.     QPushButton *button=new QPushButton(dialog);
  502.     button->move(65,130);
  503.     button->setText(tr(\"确定\"));
  504.     dialog->show();
  505.     connect(button,SIGNAL(clicked()),this,SLOT(DecreseVoice()));
  506. }
  507. //将图像的像素信息存在缓存中,并通过调用图像平滑函数更改缓存中的信息
  508. void MainWindow::DecreseVoice()
  509. {
  510.     image=new QImage(fileName);
  511.     int i,j,k,num;
  512.     int width=image->width(),height=image->height();
  513.     QImage MoreClear;
  514.     MoreClear=QImage(width,height,QImage::Format_ARGB32);
  515.     num=width*height;
  516.     QRgb tmpPixel[num];
  517.     int yanKind=setKind->value();
  518.     for(i=0;i<width;i++)
  519.     {
  520.         for(j=0;j<height;j++)
  521.         {
  522.             k=i*height+j;
  523.             tmpPixel[k]=image->pixel(i,j);
  524.         }
  525.     }
  526.     MoreClearPic(tmpPixel,yanKind,width,height);
  527.     for(i=0;i<width;i++)
  528.     {
  529.         for(j=0;j<height;j++)
  530.         {
  531.             k=i*height+j;
  532.             MoreClear.setPixel(i,j,tmpPixel[k]);
  533.         }
  534.     }
  535.     ui->label_2->resize(width,height);
  536.     ui->label_2->setPixmap(QPixmap::fromImage(MoreClear));
  537.     delete dialog;
  538. }
  539. //,图形平滑函数,它通过调用相应的平滑化函数实现图像的不同平滑化
  540. void MainWindow::MoreClearPic(QRgb *tmpPixel,int yanKind,int width,int height)
  541. {
  542.     int i,j,k;
  543.     int num=width*height;
  544.     int rtmpPixel[num],gtmpPixel[num],btmpPixel[num];
  545.     for(i=0;i<width;i++)
  546.     {
  547.        for(j=0;j<height;j++)
  548.        {
  549.            k=i*height+j;
  550.            rtmpPixel[k]=qRed(tmpPixel[k]);
  551.            gtmpPixel[k]=qGreen(tmpPixel[k]);
  552.            btmpPixel[k]=qBlue(tmpPixel[k]);
  553.        }
  554.     }
  555.     if(yanKind==1)
  556.     {
  557.         YanMo1(rtmpPixel,width,height);
  558.         YanMo1(gtmpPixel,width,height);
  559.         YanMo1(btmpPixel,width,height);
  560.     }
  561.     if(yanKind==2)
  562.     {
  563.         YanMo2(rtmpPixel,width,height);
  564.         YanMo2(gtmpPixel,width,height);
  565.         YanMo2(btmpPixel,width,height);
  566.     }
  567.     /*if(yanKind==3)
  568.     {
  569.         YanMo3(rtmpPixel,width,height);
  570.         YanMo3(gtmpPixel,width,height);
  571.         YanMo3(btmpPixel,width,height);
  572.     }*/
  573.     for(i=1;i<width-1;i++)
  574.     {
  575.         for(j=1;j<height-1;j++)
  576.         {
  577.             k=i*height+j;
  578.             tmpPixel[k]=qRgb(rtmpPixel[k],gtmpPixel[k],btmpPixel[k]);
  579.         }
  580.     }
  581. }
  582. //邻域平均法平滑化函数
  583. void MainWindow::YanMo1(int *tmpPixel, int width, int height)
  584. {
  585.     float Template[9]={1.0/9,1.0/9,1.0/9,1.0/9,1.0/9,1.0/9,1.0/9,1.0/9,1.0/9};
  586.     int i,j;
  587.     for(i=1;i<width-1;i++)
  588.     {
  589.        for(j=1;j<height-1;j++)
  590.        {
  591.          tmpPixel[i*height+j]=tmpPixel[(i-1)*height+j-1]*Template[0]+tmpPixel[(i-1)*height+j]*Template[1]+
  592.          tmpPixel[(i-1)*height+j+1]*Template[2]+tmpPixel[i*height+j-1]*Template[3]+tmpPixel[i*height+j]*Template[4]
  593.          +tmpPixel[i*height+j+1]*Template[5]+tmpPixel[(i+1)*height+j-1]*Template[6]+tmpPixel[(i+1)*height+j]*Template[7]
  594.          +tmpPixel[(i+1)*height+j+1]*Template[8];
  595.        }
  596.     }
  597. }
  598. //加权平均法平滑化函数
  599. void MainWindow::YanMo2(int *tmpPixel, int width, int height)
  600. {
  601.     float Template[9]={1.0/16,2.0/16,1.0/16,2.0/16,4.0/16,2.0/16,1.0/16,2.0/16,1.0/16};
  602.     int i,j;
  603.     for(i=1;i<width-1;i++)
  604.     {
  605.        for(j=1;j<height-1;j++)
  606.        {
  607.          tmpPixel[i*height+j]=tmpPixel[(i-1)*height+j-1]*Template[0]+tmpPixel[(i-1)*height+j]*Template[1]+
  608.          tmpPixel[(i-1)*height+j+1]*Template[2]+tmpPixel[i*height+j-1]*Template[3]+tmpPixel[i*height+j]*Template[4]
  609.          +tmpPixel[i*height+j+1]*Template[5]+tmpPixel[(i+1)*height+j-1]*Template[6]+tmpPixel[(i+1)*height+j]*Template[7]
  610.          +tmpPixel[(i+1)*height+j+1]*Template[8];
  611.        }
  612.     }
  613. }
2014-08-10 16:35:13 keybord_dancer 阅读数 6723
  • OpenSceneGraph与qt结合视频教程

    Qt中嵌入OSG控件教程,教大家.认识并简单的应用qt,达到可以做一些自己的小例子;qt与osg是如何传递消息的,如何进行通信;了解三维是如何显示在里。有问题咨询老师微信,微信号:mikeshizhanbiao

    22755 人正在学习 去看看 师占标

为了学习Qt界面编程和图像处理的基础算法,本人使用实现制作了一个简单的图像处理软件,实现了大部分的图像处理的基础算法,在这里放出来与大家交流下,欢迎大家不吝指教。

项目源码地址 https://github.com/Aaron-Cai/ImageProcessTool.git

本文是这个系列的第一篇文章,将首先先介绍一下软件最终的实现效果。软件组合要实现了一下一些基本的图像处理操作,包括:

1、 二值化(手动二值化,Otsu二值化,和熵二值)

2、卷积和基于卷积的操作(滤波、边缘提取)

3、形态学操作(膨胀、腐蚀、开闭运算) 以及基于形态学的其他操作(边缘提取、区域提取、灰度重建等等)

 

使用的开发环境:

VS2008 +Qt 4

 

先贴几张图

二值化

 

 

使用索贝尔算子提取边缘

 

使用形态学操作对二值图像进行骨架提取:

 

使用形态学操作提取特定区域(红色部分为提取结果)

 

2016-03-05 12:45:16 u010899190 阅读数 767
  • OpenSceneGraph与qt结合视频教程

    Qt中嵌入OSG控件教程,教大家.认识并简单的应用qt,达到可以做一些自己的小例子;qt与osg是如何传递消息的,如何进行通信;了解三维是如何显示在里。有问题咨询老师微信,微信号:mikeshizhanbiao

    22755 人正在学习 去看看 师占标

主界面
主界面

原图
原图

方框滤波

均值滤波

高斯滤波

中值滤波

双边滤波

图像处理之滤波1代码

2019-02-13 15:28:47 qq_27131611 阅读数 379
  • OpenSceneGraph与qt结合视频教程

    Qt中嵌入OSG控件教程,教大家.认识并简单的应用qt,达到可以做一些自己的小例子;qt与osg是如何传递消息的,如何进行通信;了解三维是如何显示在里。有问题咨询老师微信,微信号:mikeshizhanbiao

    22755 人正在学习 去看看 师占标

Qt C++:综合数字图像处理平台–登录界面设计

如何设计一个登陆界面

网络上关于利用Qt设计登录界面的例程很多,实现的复杂度不同功能也相应有所区别。
Qt封装实现了强大的对话框功能(后面有时间专门写一章详细介绍Qt的对话框使用的文章),通常我们使用对话框来实现短期任务和用户交互。在这次的项目中采用一种简单的逻辑实现–QDialog实现。
程序运行后,首先创建一个包含QLabel(文本信息提示)、QLineEdit(用户信息处理)、QCheckBox、QPushButton等一系列功能控件的对话框,在对话框内对相应控件的数据、功能进行处理,实现登录用户的信息验证、新用户注册等功能。由于初次学习使用Qt,登录功能的设计未使用数据库信息存储等高级功能,每个例程只能注册使用一个用户,此外,用户数据的安全性无法保证(从下文的实现代码可以看到)。等后面功力深厚了再做优化吧~

界面设计

登录界面设计如上图所示,QLineEdit实现用户名、密码输入,QCheckBox对是否记住密码进行选择,QPushButton按钮实现注册与登录功能,此外,可以根据自己的需求选择登录界面的背景图。
登录界面的右上角设计为两个QToolButton,实现登录界面的最小化与关闭。由于指定了登录窗口时钟保持置顶显示,最小化按钮未启用。

登录界面各控件命名如上图所示。

代码分析

这部分详细介绍代码实现,部分分析见代码注释。
DialogLogin继承自QDialog,此部分代码为DialogLogin的初始化(构造)与析构函数。

dialoglogin.cpp
//需要用到的相关头文件
#include <QMouseEvent>
#include <QSettings>
#include <QMessageBox>
#include <QByteArray>
#include <QCryptographicHash>
#include <QBitmap>
#include <QPainter>
#include "dialoglogin.h"
#include "ui_dialoglogin.h"
//DialogLogin构造函数
DialogLogin::DialogLogin(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DialogLogin){
    ui->setupUi(this);
    this->setAttribute(Qt::WA_DeleteOnClose);                         //设置该窗口为关闭时删除
    this->setWindowFlags(Qt::SplashScreen|Qt::WindowStaysOnTopHint);  //设置为SplashScreen, 窗口无边框 窗口置顶显示
    QBitmap bmp(this->size());      //创建一张与当前窗口大小一样的位图
    bmp.fill();                     //初始化位图  默认Qt::white
    QPainter p(&bmp);
    p.setPen(Qt::NoPen);
    p.setBrush(Qt::black);          //设置画刷颜色
    p.drawRoundedRect(bmp.rect(),10,10);   //在QBitmap上绘制一个带圆角的区域
    setMask(bmp);                   //设置窗口遮罩 实现登录界面圆角效果
    
    ui->LoginPSWD->setEchoMode(QLineEdit::Password); //设置QLineEdit LoginPSWD为密码输入模式 即输入不可见
    
    ui->ButtLoginClose->setStyleSheet(  //关闭按钮样式表
        "QToolButton{background-color:transparent}" //正常状态下
        "QToolButton:pressed{background-color:red}" //鼠标按下样式
        "QToolButton:hover{background-color:red}"); //鼠标悬停样式
    readSettings();   //读注册表  登陆参数
}
//DialogLogin 析构函数
DialogLogin::~DialogLogin(){
    delete ui;
}

槽函数,注册与登录按钮功能实现

/************************************************************
*函数:on_ButtLOGIN_clicked()
*参数:无
*功能:登陆按钮的槽函数
*返回值:无
*备注:无
************************************************************/
void DialogLogin::on_ButtLOGIN_clicked(){
    QString user=ui->LoginUserName->text().trimmed();  //获取输入用户名
    QString pswd=ui->LoginPSWD->text().trimmed();      //获取输入密码
    if ((user == m_user)&&(pswd == m_pswd)) {          //检查用户名和密码是否正确
        writeSettings();   //保存设置
        this->accept();    //对话框 accept(),关闭对话框
    }
    else{
        m_tryCount++;      //统计错误次数
        if (m_tryCount>3){ //允许连续输错3次密码
            QMessageBox::critical(this, "错误", "输入错误次数太多,强行退出");
            this->reject(); //退出
        }
        else
            QMessageBox::warning(this, "错误提示", "用户名或密码错误");
    }
}
/************************************************************
*函数:on_ButtLoginRegister_clicked()
*参数:无
*功能:注册按钮的槽函数
*返回值:无
*备注:无
************************************************************/
void DialogLogin::on_ButtLoginRegister_clicked(){
    QString NewUser = ui->LoginUserName->text().trimmed();  //获取输入用户名
    QString NewPSWD = ui->LoginPSWD->text().trimmed();      //获取输入密码
    if(QString(NewUser).isEmpty()){       //检查用户名合法性  不为空即可
        QMessageBox::warning(this, tr(""), tr("用户名格式错误   \r\n请重新输入!   "));
    }
    else if(QString(NewPSWD).isEmpty()){  //检查密码合法性
        QMessageBox::warning(this, tr(""), tr("密码格式错误     \r\n请重新输入!   "));
    }
    else{    //用户名密码均无误允许注册 简单注册 只能保存一个账户  新用户会覆盖旧用户
        if(QMessageBox::Yes == QMessageBox::question(this,
                                                      tr(""),
                                                      tr("新的账号密码将会覆盖旧的账户,是否创建?"),
                                                      QMessageBox::Yes | QMessageBox::No,
                                                      QMessageBox::Yes)){
            m_user = NewUser;
            m_pswd = NewPSWD;
            writeSettings();   //保存设置  新账户
            QMessageBox::information(this, tr(""), tr("注册成功!"));
        }
        else{
            QMessageBox::information(this, tr(""), tr("注册失败!"));
        }
    }
}

用户登录数据的读写与校验实现。

/************************************************************
*函数:readSettings()
*参数:无
*功能:读取存储的用户名和密码
*返回值:无
*备注:无
************************************************************/
void DialogLogin::readSettings()
{
    QString organization="Shawn-Qt";//用于注册表,
    QString appName="DIP_Demo";   
    QSettings  settings(organization,appName);//创建
    bool saved=settings.value("saved",false).toBool();   //读取 saved键的值
    m_user=settings.value("Username","User").toString();  //读取 Username 键的值,缺省为“user”
    m_pswd=settings.value("PSWD","12345").toString();     //读取PSWD
    ui->LoginUserName->setText(m_user);
    if(saved){  //如果之前有保存  调用  默认显示旧的账号密码
        ui->LoginPSWD->setText(m_pswd);
    }
    ui->LoginRemb->setChecked(saved);
}
/************************************************************
*函数:writeSettings()
*参数:无
*功能:保存用户名,密码等设置
*返回值:无
*备注:无
************************************************************/
void DialogLogin::writeSettings(){
    QSettings   settings("WWB-Qt","DIP_Demo"); //注册表键组
    settings.setValue("Username",m_user);      //用户名
    settings.setValue("PSWD",m_pswd);          //密码
    settings.setValue("saved",ui->LoginRemb->isChecked());   //记住密码选项保存
}

重载鼠标操作函数实现登录界面鼠标任意点可拖动。

/****************************************************
*函数:mousePressEvent(QMouseEvent *event)
*参数:*event  鼠标事件指针
*功能:重载鼠标点击事件函数 监测鼠标左键按下使能窗口移动
*返回值:无
*备注:该函数在鼠标点击动作下触发
****************************************************/
void DialogLogin::mousePressEvent(QMouseEvent *event){ 
    if (event->button() == Qt::LeftButton){  //如果是左键点击
        m_moving = true;                     //使能窗口移动
        //记录下鼠标相对于窗口的位置
        //event->globalPos()鼠标按下时,鼠标相对于整个屏幕位置
        //pos()->this->pos()鼠标按下时,窗口相对于整个屏幕位置
        m_lastPos = event->globalPos() - pos();
    }
    return QDialog::mousePressEvent(event);
}
/****************************************************
*函数:mouseMoveEvent(QMouseEvent *event)
*参数:*event  鼠标事件指针
*功能:重载鼠标移动事件函数 在移动使能下移动窗口位置
*返回值:无
*备注:该函数在鼠标移动动作下触发
****************************************************/
void DialogLogin::mouseMoveEvent(QMouseEvent *event){
    //(event->buttons() && Qt::LeftButton)按下是左键
    //鼠标移动事件需要移动窗口,窗口移动到哪里呢?就是要获取鼠标移动中,窗口在整个屏幕的坐标,然后move到这个坐标,怎么获取坐标?
    //通过事件event->globalPos()知道鼠标坐标,鼠标坐标减去鼠标相对于窗口位置,就是窗口在整个屏幕的坐标
    if (m_moving && (event->buttons() && Qt::LeftButton)
        && (event->globalPos()-m_lastPos).manhattanLength() > QApplication::startDragDistance()){
        move(event->globalPos()-m_lastPos);
        m_lastPos = event->globalPos() - pos();
    }
    return QDialog::mouseMoveEvent(event);
}
/****************************************************
*函数:mouseReleaseEvent(QMouseEvent *event)
*参数:*event  鼠标事件指针
*功能:重载鼠标按键释放事件函数 失能窗口移动
*返回值:无
*备注:该函数在鼠标按键释放动作下触发
****************************************************/
void DialogLogin::mouseReleaseEvent(QMouseEvent *event){
    event->globalPos();
    m_moving=false;      //停止移动
}

小结

登录界面的制作还是很容易的,可以使用对话框(QDialog)或者直接QWidget,其实本质都是一样的,QDialog也是继承自QWidget,只是QDialog在做登录界面时界面间传递信息方便些(继承类封装了多一些函数,功能指向性强一些而已)。
能力问题,对于注册用户,仅使用了简单的注册表保存数据,安全性没有保障,且只能同时注册使用一个用户,新用户会覆盖就用户的账户密码信息。
个人认为这部分比较有意思的是界面的样式设计,相信你在写一个功能牛逼的软件时是不会给它配上一个Low Low的XP风格界面的。这里只是使用了一个简单的圆角处理,得到一个圆角的登录界面。
详细分析下这段代码,掌握了这种方式可以设计任意形状你想要的牛逼界面。

	QBitmap bmp(this->size());         //创建一张与当前窗口大小一样的位图
    bmp.fill();                        //初始化位图  默认Qt::white
    QPainter p(&bmp);                  //使用QPainter对QBitmap进行绘制
    p.setPen(Qt::NoPen);               //设置相关画图参数
    p.setBrush(Qt::black);             //设置画刷颜色
    //配置完绘制工具  调用你需要的函数对Bitmap 绘制
    p.drawRoundedRect(bmp.rect(),10,10);   //在QBitmap上绘制一个带圆角的区域
    setMask(bmp);                   //设置窗口遮罩 实现登录界面圆角效果

此处对窗口使用setMask函数,即是为窗口添加一个遮罩bmp。
遮罩图片为Black的地方显示窗口内容,White的地方为透明(不显示)。
第2行代码QBitmap.fill函数初始化位图为White。
第5行代码设置QPainter画刷为Black。
第7行代码在与窗口大小相同全为White的Bitmap上绘制了一个黑色的带圆角的区域。
执行setMask函数后便是黑色区域正常显示,其他区域透明显示,实现圆角窗口的效果。
其实这里不一定要是黑色区域,配置画刷为red、green、blue都可以,原因可以去研究setMask的实现 [呲牙]。
总的来说,你需要先绘制好一副你需要的形状的遮罩图形,使用这个图片去对窗口进行遮罩处理即可得到你要的界面。图片可以代码绘制也可以是文件的形式加载,看你需要咯~
参考例程:https://download.csdn.net/download/qq_27131611/10955676

2019-06-11 16:43:18 WHU_Kevin_Lin 阅读数 1085
  • OpenSceneGraph与qt结合视频教程

    Qt中嵌入OSG控件教程,教大家.认识并简单的应用qt,达到可以做一些自己的小例子;qt与osg是如何传递消息的,如何进行通信;了解三维是如何显示在里。有问题咨询老师微信,微信号:mikeshizhanbiao

    22755 人正在学习 去看看 师占标

问题描述

使用Qt的QGraphicsView显示图像时,鼠标滚轮的动作由其自带的wheelEvent事件控制。滚动滚轮可以控制图像上下移动。

现希望通过滚动滚轮实现图像缩放,且缩放的中心为鼠标所在位置。

解决方案

1. 自定义GraphicsView

HighGraphicsView类继承自QGraphicsView类,重写了wheelEventmouseMoveEvent两个事件。其中,对mouseMoveEvent,在原有的基础上加入了触发鼠标位置变化的事件,这个鼠标位置是相对于View(x,y)坐标。对wheelEvent,放弃原有事件,记录滚动间隔,发送信号。

HighGraphicsView.h

#pragma once
#include <qgraphicsview.h>
#include <QMouseEvent>
#include <QWheelEvent>

#include <QScrollBar>

class HighGraphicsView :
	public QGraphicsView
{
	Q_OBJECT

public:
	HighGraphicsView(QWidget *parent = nullptr);
	~HighGraphicsView();

signals:
	void mousePositionChanged(int x, int y);
	void wheelScrollChanged(int step);

protected:
	void wheelEvent(QWheelEvent *event);
	void mouseMoveEvent(QMouseEvent *event);

private:
	// Mouse Position
	int x, y;
};

HighGraphicsView.cpp

#include "HighGraphicsView.h"


HighGraphicsView::HighGraphicsView(QWidget *parent)
	: QGraphicsView(parent)
{
}


HighGraphicsView::~HighGraphicsView()
{
}

void HighGraphicsView::wheelEvent(QWheelEvent *event)
{
	QPoint numPixels, numDegrees;
	numPixels = event->pixelDelta();
	numDegrees = event->angleDelta() / 8;

	int step = 0;
	if (!numPixels.isNull())
	{
		step = numPixels.y();
	}
	else if (!numDegrees.isNull())
	{
		QPoint numSteps = numDegrees / 15;
		step = numSteps.y();
	}

	// Enlarge: +; Shrink: -
	emit wheelScrollChanged(step);
}

void HighGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
	QGraphicsView::mouseMoveEvent(event);

	x = event->x();
	y = event->y();

	emit mousePositionChanged(x, y);
}

2. 记录鼠标位置

鼠标的位置包括三类:

  1. 图像上的位置;

(x0,y0) (x_0,y_0)

  1. View中的位置;

(x,y) (x,y)

  1. Scene中的位置;

(X,Y) (X,Y)

其对应的转换关系如下所示:

{x0=XscaleXy0=YscaleY{X=x+horizontal=x+hY=y+vertical=y+v \begin{cases} x_0 = X * scaleX \\ y_0 = Y * scaleY \end{cases}\\ \begin{cases} X = x + horizontal = x + h\\ Y = y + vertical = y + v \end{cases}

其中,horizontalhorizontalView->horizontalScrollBar()->value()的值,verticalverticalView->verticalScrollBar()->value()的值,scaleX,scaleYscaleX, scaleY是当前图像x,yx,y方向上的缩放比例,其表达式为:

{scaleX=WidthcurrentWidthscaleY=HeightcurrentHeight \begin{cases} scaleX = \frac{Width}{currentWidth} \\ scaleY = \frac{Height}{currentHeight} \\ \end{cases}

在引用HighGraphicsView的类中,存储两类鼠标位置(x0,y0),(x,y)(x_0,y_0), (x,y)

// Mouse Position
int x, y;         // x0,y0
int viewX, viewY; // x,y

创建槽onMousePositionChanged,用来接收View发出的mousePositionChanged信号

void onMousePositionChanged(int x, int y)
{
	viewX = x;
	viewY = y;

	QRectF rect = View->mapToScene(View->viewport()->geometry()).boundingRect();
	x += int(rect.x() - 1); // Rectangle begin with (1,1)
	y += int(rect.y() - 1);

	x = int(double(x) * (double(Width) / double(currentWidth)));
	y = int(double(y) * (double(Height) / double(currentHeight)));

	this->x = x;
	this->y = y;

	if (x >= Width || x < 0 || y >= Height || y < 0)
	{
		ui.statusBar->showMessage(u8"Outside");
	}
	else
	{
		ui.statusBar->showMessage(QString().sprintf(u8"(x=%d, y=%d)", x, y));
	}
}

绑定信号与槽

// Receive (x,y) coordinate
connect(View, SIGNAL(mousePositionChanged(int, int)), this, SLOT(onMousePositionChanged(int, int)));

3. 图像缩放

要以鼠标为中心进行图像缩放,可以分为两个步骤进行:1. 缩放;2. 平移。缩放过程较为简单,只需要根据比例对原图进行缩放即可。平移的目的是为了使图像在缩放前后鼠标所在的位置相对于图像不变、相对于视窗(View)不变,不变量为(x,y)(x,y)、$ (x_0, y_0)$。

根据(x,y),(x0,y0),(X,Y)(x,y), (x_0,y_0), (X,Y)之间的关系(见第1小节),可以得到

x0=XscaleX=(x+h)WidthcurrentWidthy0=YscaleY=(y+v)HeightcurrentHeight x_0 = X * scaleX = \frac{(x + h) * Width}{currentWidth} \\ y_0 = Y * scaleY = \frac{(y + v) * Height}{currentHeight}

由于(x,y)(x,y)、$ (x_0, y_0)是不变量,因此可以得到变化量h,v$的值,即View相对于Scene的偏移量:

h=x0currentWidthWidthxv=y0currentHeightHeighty h = \frac{x_0 * currentWidth}{Width} - x \\ v = \frac{y_0 * currentHeight}{Height} - y

通过View->horizontalScrollBar()->setValue()View->verticalScrollBar()->setValue()设置偏移量,完成平移。

创建响应滚轮变化信号的槽:

void onWheelScrollChanged(int step)
{
	currentHeight += currentHeight / 20 * step;
	currentWidth += currentWidth / 20 * step;
	ImageItem->setPixmap(QPixmap::fromImage(Image.scaled(currentWidth, currentHeight)));

	Scene = new QGraphicsScene(this);
	Scene->addItem(ImageItem);
	View->setScene(Scene);

	int horizontal, vertical;
	horizontal = int(double(x * currentWidth) / double(Width) - viewX);
	vertical = int(double(y * currentHeight) / double(Height) - viewY);

	View->horizontalScrollBar()->setValue(horizontal);
	View->verticalScrollBar()->setValue(vertical);
}

绑定信号与槽

// Receive wheel scroll signal
connect(View, SIGNAL(wheelScrollChanged(int)), this, SLOT(onWheelScrollChanged(int)));

本节主要讲一下怎么使用QP

博文 来自: keybord_dancer
没有更多推荐了,返回首页