photo mosaic 好多张图片拼成一张完整的图片

原理:
读取原始图片,进行分割,分析每个小块RGB均值,并存储。
读取若干图片,提取并存储各个图片的RGB均值。与原始图片的每个小块进行匹配。
可以采用OpenMP进行并行加速

通过选择等级还可以设置最后 生成图片的“质量”,“清晰度”,并导出到本地。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextStream>
#include <QBoxLayout>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{QString s = QCoreApplication::applicationDirPath ();qDebug()<<s;ui->setupUi(this);m_matchflag = -1;m_wnum = 0;m_hnum = 0;m_zoomBase = 1;m_zoomMos = 1;ui->zoomBig1->setVisible(false);ui->zoomBig2->setVisible(false);ui->zoomSmall1->setVisible(false);ui->zoomSmall2->setVisible(false);m_base = new QLabel(this);m_mosaic = new QLabel(this);m_mosaicImg = new QImage();m_baseImg2 = new QImage();m_baseImg = new IplImage();m_saveDialog = new MsaveDialog(this);m_saveDialog->hide();connect(ui->baseimg, QPushButton::clicked,this,MainWindow::askMainImagePath);connect(ui->subimg, QPushButton::clicked,this,MainWindow::askSubImageDir);connect(ui->start, QPushButton::clicked,this,MainWindow::startLoadeImgInfo);connect(m_saveDialog,MsaveDialog::saveMosaic,this,MainWindow::saveMosaic);ui->scrollArea->setWidget(m_base);ui->scrollArea_2->setWidget(m_mosaic);ui->baseimg->setStyleSheet("QPushButton""{""border-radius:15px;"" background-color: rgb(0, 170, 255);""color: rgb(255, 255, 255);""font-size:26px;""font-family:System;""}""QPushButton:pressed{""background:rgb(86, 128, 136);""}");ui->subimg->setStyleSheet("QPushButton""{""border-radius:15px;"" background-color: rgb(0, 170, 255);""color: rgb(255, 255, 255);""font-size:26px;""font-family:System;""}""QPushButton:pressed{""background:rgb(86, 128, 136);""}");ui->start->setStyleSheet("QPushButton""{""border-radius:15px;"" background-color: rgb(150,150,150);""color: rgb(255, 255, 255);""font-size:26px;""font-family:System;""}");}void MainWindow::askSubImageDir()
{QString subFilePath = QFileDialog::getExistingDirectory(0, "Select the directory of pictures","./",QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks);QDir directory(subFilePath);directory.setFilter(QDir::Files | QDir::NoSymLinks);QFileInfoList infoList= directory.entryInfoList();m_subImgPath.clear();int size = infoList.size();for (int i = 0; i < size; i++){m_subImgPath.append(infoList.at(i).filePath());}m_matchflag++;if(m_matchflag){ui->start->setEnabled(true);ui->start->setStyleSheet("QPushButton""{""border-radius:15px;"" background-color: rgb(0, 170, 255);""color: rgb(255, 255, 255);""font-size:26px;""font-family:System;""}""QPushButton:pressed{""background:rgb(86, 128, 136);""}");}}void MainWindow::askMainImagePath()
{m_baseImgPath= QFileDialog::getOpenFileName(0,"Select the Base picture","","Images (*.jpg *.jpeg *.png)");m_baseImg =cvLoadImage(m_baseImgPath.toStdString().data());if(!m_baseImg)return;m_baseImg2 =IplImageToQImage(m_baseImg);int width = m_baseImg2->width(),height =m_baseImg2->height();while(width*height >400000){width /=1.41;height /=1.41 ;}QImage tempimg = m_baseImg2->scaled(QSize(width,height), Qt::KeepAspectRatio,Qt::SmoothTransformation);QPixmap pic(QPixmap::fromImage(tempimg));m_base->setPixmap(pic);m_base->resize(QSize(pic.width(),pic.height()));m_zoomBase = 1;ui->zoomBig1->setVisible(true);ui->zoomSmall1->setVisible(true);m_matchflag++;if(m_matchflag){ui->start->setEnabled(true);ui->start->setStyleSheet("QPushButton""{""border-radius:15px;"" background-color: rgb(0, 170, 255);""color: rgb(255, 255, 255);""font-size:26px;""font-family:System;""}""QPushButton:pressed{""background:rgb(86, 128, 136);""}");}// cvReleaseImage(&tempImg);}
void MainWindow::startLoadeImgInfo()
{delete m_mosaicImg;m_mosaicImg = new QImage();m_mosaicImg = IplImageToQImage(m_baseImg);m_baseInfoCache.clear();m_subInfoCache.clear();m_subImgCache.clear();m_zoomMos = 1;int width =m_baseImg->width,height =m_baseImg->height;int rank = ui->comboBox->currentIndex();int devide;switch(rank){case 0: devide=25;break;case 1: devide= 50;break;case 2:devide= 100;break;case 3:devide= 200;break;case 4:devide= 400;break;default: break;}qDebug()<<"rank:"<<rank<<"\n";m_subLen =(width<height?width:height)/devide;if(m_subLen < 1)m_subLen = 1;QProgressDialog pd(this);pd.setWindowTitle("Please Wait");pd.setLabelText("processing photos..... ^u^");pd.setRange(0,0);pd.setCancelButton(NULL);pd.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);QFutureWatcher<void> watcher_base(this);QFuture<void> lodeBaseThread =  QtConcurrent::run(this,loadBaseImgInfo);QObject::connect(&watcher_base,SIGNAL(finished()),&pd,SLOT(reset()));QObject::connect(&pd,SIGNAL(canceled()),&watcher_base,SLOT(cancel()));watcher_base.setFuture(lodeBaseThread);pd.exec();watcher_base.waitForFinished();QProgressDialog pd2(this);pd2.setWindowTitle("Please Wait");pd2.setLabelText("processing  photos..... ^u^");pd2.setRange(0,0);pd2.setCancelButton(NULL);pd2.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);QFutureWatcher<void> watcher_sub(this);QFuture<void> lodeSubThread = QtConcurrent::run(this,loadSubImgInfo);QObject::connect(&watcher_sub,SIGNAL(finished()),&pd2,SLOT(reset()));QObject::connect(&pd2,SIGNAL(canceled()),&watcher_sub,SLOT(cancel()));watcher_sub.setFuture(lodeSubThread);pd2.exec();watcher_sub.waitForFinished();match();}
QImage* MainWindow::IplImageToQImage(const IplImage *pIplImage)
{QImage *qImage;int w = pIplImage->width;int h = pIplImage->height;qImage = new QImage(w, h, QImage::Format_RGB32);int x, y;for(x = 0; x < pIplImage->width; ++x){for(y = 0; y < pIplImage->height; ++y){CvScalar color = cvGet2D(pIplImage, y, x);int r = color.val[2];int g = color.val[1];int b = color.val[0];qImage->setPixel(x, y, qRgb(r,g,b));}}return qImage;
}
void MainWindow::loadSubImgInfo()
{CvScalar avg = cvScalarAll(0);QImage *qimg;int len;//int flag =0 ;qDebug()<<"number:"<<m_subImgPath.size()<<"\n";// #pragma omp parallel forfor(int i = 0;i<m_subImgPath.size();i++){IplImage * img = cvLoadImage(m_subImgPath.at(i).toStdString().data(),CV_LOAD_IMAGE_COLOR);len= img->width<img->height?img->width:img->height;IplImage *img2 = cvCreateImage(cvSize(img->width*m_subLen/len,img->height*m_subLen/len),img->depth,img->nChannels);cvResize(img, img2, CV_INTER_LINEAR);cvSetImageROI(img2,cvRect(0,0,m_subLen,m_subLen));IplImage *dst = cvCreateImage(cvSize(m_subLen,m_subLen),IPL_DEPTH_8U,img2->nChannels);cvCopy(img2,dst,0);cvResetImageROI(img2);qimg =IplImageToQImage(img2);// #pragma omp criticalm_subImgCache.append(*qimg);// qDebug()<<i<<"\n";avg = cvAvg(img2);//  #pragma omp criticalm_subInfoCache.append(avg);// flag++;// qDebug()<<flag<<"\n";cvReleaseImage(&img2);cvReleaseImage(&dst);cvReleaseImage(&img);}qDebug()<<"number:"<<m_subInfoCache.size()<<"\n";
}void MainWindow::loadBaseImgInfo()
{m_hnum = 0;m_wnum = 0;int width =m_baseImg->width,height =m_baseImg->height;CvRect subRect;CvMat *model = cvCreateMat(m_subLen, m_subLen, CV_8U);CvScalar avg = cvScalarAll(0);for (int i = 0; i<height; i = i + m_subLen){m_hnum++;for (int j = 0; j<width; j = j + m_subLen){int temp_w,temp_h;if(j+m_subLen>width)temp_w = width-j;else temp_w = m_subLen;if(i+m_subLen>height)temp_h = height-i;else temp_h = m_subLen;subRect = cvRect(j, i,temp_w,temp_h);cvGetSubRect(m_baseImg, model, subRect);avg = cvAvg(model);m_baseInfoCache.append(avg);}}m_wnum = m_baseInfoCache.size()/m_hnum;qDebug()<<"the number of mosaic:"<<m_hnum*m_wnum<<"\n";cvReleaseMat(&model);}void MainWindow::match()
{QElapsedTimer timer;timer.start();QProgressDialog pd3(this);pd3.setWindowTitle("Please Wait");pd3.setLabelText("Creating mosaic.....");pd3.setRange(0,0);pd3.setCancelButton(NULL);pd3.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint);QFutureWatcher<void> watcher_mosaic(this);QFuture<void> mosaicThread =  QtConcurrent::run(this,findBestSub);QObject::connect(&watcher_mosaic,SIGNAL(finished()),&pd3,SLOT(reset()));QObject::connect(&pd3,SIGNAL(canceled()),&watcher_mosaic,SLOT(cancel()));watcher_mosaic.setFuture(mosaicThread);pd3.exec();watcher_mosaic.waitForFinished();mosaicThread.waitForFinished();int width = m_mosaicImg->width(),height = m_mosaicImg->height();while(width*height >400000){width /=1.41;height /=1.41 ;}QImage tempimg = m_mosaicImg->scaled(QSize(width,height), Qt::KeepAspectRatio,Qt::SmoothTransformation);QPixmap pic(QPixmap::fromImage(tempimg));m_mosaic->setPixmap(pic);m_mosaic->resize(QSize(pic.width(),pic.height()));m_saveDialog->show();ui->zoomBig2->setVisible(true);ui->zoomSmall2->setVisible(true);qDebug() << "processing photos takes " << timer.elapsed() << "milliseconds";
}
void MainWindow::drawSubImg(QPoint pos,int num)
{QPainter painter(m_mosaicImg);QImage img = m_subImgCache.at(num);//,img2;painter.drawImage(pos,img);}int MainWindow::calculateDis2(CvScalar point1,CvScalar point2)
{return (pow(point1.val[0]-point2.val[0],2)+pow(point1.val[1]-point2.val[1],2)+pow(point1.val[2]-point2.val[2],2));
}void MainWindow::findBestSub()
{QElapsedTimer timer;timer.start();int min = 255*255*3,x = 0,y = 0, tmin,tnum,re;for(int i = 0 ; i< m_baseInfoCache.size();i++){tmin = min,tnum = -1;for(int j = 0; j < m_subInfoCache.size();j++){re =calculateDis2(m_baseInfoCache.at(i),m_subInfoCache.at(j));if(re<tmin){tnum = j;tmin = re;}}y = i/m_wnum;x = i%m_wnum;drawSubImg(QPoint(x*m_subLen,y*m_subLen),tnum);}qDebug() << "creating mosaic takes" << timer.elapsed() << "milliseconds";
}void MainWindow::saveMosaic()
{QString filename = QFileDialog::getSaveFileName(this,tr("Save Image"),"",tr("Images (*.jpg)"));if(filename.isEmpty()){return;}else{if(! ( m_mosaicImg->save(filename) ) ){QMessageBox::information(this,tr("Failed to save the mosaics"),tr("Failed to save the mosaics!"));return;}else{QMessageBox::information(this,tr("successfully  save the mosaics"),tr("successfully  save the mosaics!"));}}
}MainWindow::~MainWindow()
{delete ui;delete  m_baseImg;delete m_mosaicImg;delete m_base;delete m_mosaic;delete m_mosaicImg;
}
void MainWindow::baseimgZoom(const qreal &zoom)
{QImage tempimg= m_baseImg2->scaled(m_baseImg2->width()*zoom,m_baseImg2->height()*zoom,Qt::KeepAspectRatio,Qt::SmoothTransformation);QPixmap pic(QPixmap::fromImage(tempimg));m_base->setPixmap(pic);m_base->resize(QSize(pic.width(),pic.height()));}
void MainWindow::mosaicImgZoom(const qreal &zoom)
{QImage tempimg= m_mosaicImg->scaled(QSize(m_mosaicImg->width()*zoom,m_mosaicImg->height()*zoom),Qt::KeepAspectRatio,Qt::SmoothTransformation);QPixmap pic(QPixmap::fromImage(tempimg));m_mosaic->setPixmap(pic);m_mosaic->resize(QSize(pic.width(),pic.height()));}
void MainWindow::on_zoomBig1_clicked()
{if(m_zoomBase>5)return;m_zoomBase *= 1.100;baseimgZoom(m_zoomBase);}void MainWindow::on_zoomSmall1_clicked()
{if(m_zoomBase<0.1)return;m_zoomBase *= 0.900;baseimgZoom(m_zoomBase);
}void MainWindow::on_zoomBig2_clicked()
{if( m_zoomMos>5)return;m_zoomMos *= 1.100;mosaicImgZoom(m_zoomMos);
}void MainWindow::on_zoomSmall2_clicked()
{if(m_zoomMos<0.1)return;m_zoomMos *= 0.900;mosaicImgZoom(m_zoomMos);
}

photo mosaic 拼图马赛克相关推荐

  1. 【R语言】【可视化】 之 Mosaic Plot(马赛克图)

    Mosaic plot常常用来展示Categorical data(分类数据)(关于不同的数据类别,参照连接更严谨英文比较好的朋友可以看[1]),mosaic plot 强大的地方在于它能够很好的展示 ...

  2. Mosaic(马赛克)数据增强总结

    文章目录 1.推荐链接 2.argparse.ArgumentParser解析 3.用Mosaic制作菜刀数据集 4.关于数据增强比较好的链接 1.推荐链接 1.图片的左右翻转,上下翻转,旋转 参考: ...

  3. 用Java实现的简易马赛克拼图

    用Java实现的简易马赛克拼图 什么是马赛克拼图 效果图 原理 所有代码 什么是马赛克拼图 马赛克拼图 简单来说就是远远看上去是一张大图,放大之后会发现其实是由许多张不同的小图组成 效果图 如果准备的 ...

  4. Python 制作马赛克拼合图像

    Python 制作马赛克拼合图像 文章目录 Python 制作马赛克拼合图像 知识点 效果: 环境 原理 RGB 色彩空间 HSV 色彩空间 RGB 与 HSV 色彩空间的转换 马赛克图片拼合 数据准 ...

  5. C语言项目:图形马赛克处理技术

    每个人都有讨厌的人,例如我就比较讨厌三个姓马的人,马云.马化腾和马赛克.马云骗女人的钱,马化腾骗孩子的钱,马赛克阻挡了人们的分享和交流 .那么大家是不是知道我们今天要分享的项目是什么啦?马赛克处理技术 ...

  6. c语言动态图形代码 叮当猫,C语言制作图形马赛克处理技术,网友:这小子不进腾讯可惜了!-Go语言中文社区...

    C语言制作图形马赛克处理技术,网友:这小子不进腾讯可惜了! 每个人都有讨厌的人,例如我就比较讨厌三个姓马的人,马云.马化腾和马赛克.马云骗女人的钱,马化腾骗孩子的钱,马赛克阻挡了人们的分享和交流 .那 ...

  7. C语言制作图形马赛克处理技术,网友:这小子不进腾讯可惜了!

    每个人都有讨厌的人,例如我就比较讨厌三个姓马的人,马云.马化腾和马赛克.马云骗女人的钱,马化腾骗孩子的钱,马赛克阻挡了人们的分享和交流 .那么大家是不是知道我们今天要分享的项目是什么啦?马赛克处理技术 ...

  8. Android图片编辑马赛克效果

    1:activity代码 public class MosaicActivity extends Activity implements View.OnClickListener {private D ...

  9. 当 Python 遇到了你的微信好友

    临近毕业,慢慢的也感伤起来,回想大学这几年,除了技术的成长,最值得庆幸的就是结交了一帮志同道合的好友.后期自己做了公众号,微信好友的数量也越来越多,身边人所扮演的角色也越来越丰富,有早已结婚生子为人父 ...

最新文章

  1. Python:Bug 官网不要了,全迁去 GitHub
  2. java合并两个doc文件,java实现合并2个文件中的内容到新文件中
  3. 自己写的简易多任务系统---基于pic18fxxx
  4. 说说那些死于决斗的大牛
  5. Hbase Compaction 源码分析 - RatioBasedCompactionPolicy 策略
  6. weblogic linux sun/awt/X11GraphicsEnvironment
  7. 性能之巅:Linux网络性能分析工具
  8. Leetcode 5
  9. 运行roscore出现unable to contact my own server无法启动小海龟的部分故障问题解决
  10. c/c++ linux 进程 fork wait函数
  11. IPV6 RFC和地址表示
  12. ios5.1.1旧版软件下载_爱思助手V7.98.15 版发布:新增IPA签名旧版本应用下载等新功能...
  13. SAP ABAP 热咖啡报表模板
  14. Qt QTreeWidget/QTreeView去焦点(虚线框)
  15. pysot 中的异步多进程切图
  16. 理解进程、通过调用 fork 函数创建进程
  17. Linux必会100个命令(十六)ping、nc
  18. 学习笔记-如何设计离线跑批系统
  19. OCXO、VCXO、TCXO、DCXO、SPXO
  20. mysql怎么把只读改为读写

热门文章

  1. 北京二手房房价分析(建模篇)
  2. “互联网+”智慧农业-国稻种芯-万祥军:江西现代农业弯道赶超
  3. 黑客常用入侵方式(12种)
  4. 低噪声放大器(LNA)的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  5. 高科路由器有虚拟服务器设置吗,高科路由器怎么设置无线中继
  6. 桥接模式和中继模式的区别【转】
  7. MIPCMS模板开发之全局标签
  8. 公司起诉CTO拖延研发进度,索赔90万
  9. 图像处理Image Processing(一)
  10. EDIUS字幕窗口中保存和自动另存为该怎样区分