90年代经典“手游”—拼图板小游戏Opencv实现
来源:互联网 发布:淘宝联盟优惠券佣金 编辑:程序博客网 时间:2024/05/17 01:22
80后可能还对儿时玩过的一种经典木质的拼图板游戏记忆犹新,一般是一种4*4或5*5规格的手持活动板,通过挪动每个小板子的位置,拼出来板子上完整的图像,那时候还没有网吧,手机也还是大哥大的天下,所以这也可以算得上是最早的“手游”了吧……
简单的就是经典的,现在的Windows 7小工具里还保留了这个小游戏,当然你可能从来没有留意过~,就是下边的这个:
可以在控制面板->外观->桌面小工具里调出来。
这里准备用opencv里的模板匹配,通过鼠标响应事件来实现这个小游戏。
首先第一步是对图像按照传入的行列参数分割,并把分割出来的行*列个个数的子图像在另一空白图像中显示出来:
for(int i=0;i<rows;i++){for(int j=0;j<cols;j++){Mat SourceRoi=Sourceimage(Rect(j*Roicols,i*Roirows,Roicols-1,Roirows-1));arraryimage.push_back(SourceRoi);}}
rows和cols分别是用户定义的行列数,arraryimage是定义的 vector<Mat>类型的向量。
分割完之后需要把这些子图像随机的显示在另一空白图像中,这里写了一个生成指定区间里的不重复的随机数来实现:
//*******************************************************************////随机调换所有的子图像序列的位置,用于在 Splite image中显示//*******************************************************************//void Randarrary( vector<Mat>& vectorMat){for(int i=0;i<vectorMat.size();i++){srand(int(time(0)));int a=rand()%(vectorMat.size()-i)+i;swap(vectorMat[i],vectorMat[a]);}}
每生成一个随机数,就把该随机数作下标的向量元素跟第一个元素对换,实现生成不重复的随机数。
所有分割出来的子图像按随机顺序组成了“Splite image”图像后,通过鼠标单击事件响应函数,定位到鼠标单击点坐在的子图像,并把该子图像用模板匹配方法在原图像中定位出位置,最后合成到目标图像“Jigsaw image”
//*******************************************************************////鼠标回调函数,用于获取需要查找的子图像在原图像中的位置,并在叠加显示在目标图像中//*******************************************************************//void OnMouseAction(int event,int x,int y,int flags,void *ustc){if(event==CV_EVENT_LBUTTONDOWN){Mat RoiSpilte,RoiSource;int rows=(y/Roirows)*Roirows;int clos=(x/Roicols)*Roicols;RoiSpilte=Spilteimage(Rect(clos,rows,Roicols,Roirows));imshow("Slice",RoiSpilte);Mat image=Mat::zeros(Sourceimage.rows-Roirows,Sourceimage.cols-Roicols,CV_32FC1);matchTemplate(Sourceimage,RoiSpilte,image,1);normalize(image,image,0,1,NORM_MINMAX);double minV=0;double maxV=0;Point minP,maxP;minMaxLoc(image,&minV,&maxV,&minP,&maxP);//Mat ROIS=Sourceimage(Rect(maxP.x,maxP.y,Roicols,Roirows));Mat ROIDst=Dstimage(Rect(minP.x,minP.y,Roicols,Roirows));addWeighted(ROIDst,0,RoiSpilte,1,0,ROIDst,-1);imshow("Jigsaw image",Dstimage);}
原图像:
行列分割后的图像,子图像位置随机分布:
单击Splite image图像中的子图像,叠加该子图像到目标图像上,子图像位置通过模板匹配方法在原图像中定位:
完成后效果:
为了清楚显示边界,每个子图像在行列上都减了一个像素,所以上图可见黑色线条。
完整程序:
#include "core/core.hpp"#include "highgui/highgui.hpp"#include "imgproc/imgproc.hpp"#include <time.h>using namespace cv;Mat Sourceimage,Spilteimage,Rebuildimage,Dstimage;int rows,cols;int Roirows,Roicols;vector<Mat>arraryimage;void Randarrary( vector<Mat> &vectorMat); //随机排列子图像序列函数static int vectornumber=0;void OnMouseAction(int event,int x,int y,int flags,void *ustc); //鼠标回调事件函数int main(int argc,char*argv[]){Sourceimage=imread(argv[1]);imshow("Source image",Sourceimage);rows=atoi(argv[2]);cols=atoi(argv[3]);Roirows=Sourceimage.rows/rows;Roicols=Sourceimage.cols/cols;Spilteimage=Mat::zeros(Sourceimage.rows,Sourceimage.cols,Sourceimage.type());Dstimage=Mat::zeros(Sourceimage.rows,Sourceimage.cols,Sourceimage.type());for(int i=0;i<rows;i++){for(int j=0;j<cols;j++){Mat SourceRoi=Sourceimage(Rect(j*Roicols,i*Roirows,Roicols-1,Roirows-1));arraryimage.push_back(SourceRoi);}}// 随机函数Randarrary( arraryimage);for(int i=0;i<rows;i++){for(int j=0;j<cols;j++){Mat SpilterRoi=Spilteimage(Rect(j*Roicols,i*Roirows,Roicols-1,Roirows-1));addWeighted(SpilterRoi,0,arraryimage[vectornumber],1,0,SpilterRoi);vectornumber++;imshow("Splite image",Spilteimage);waitKey(150);}}setMouseCallback("Splite image",OnMouseAction);waitKey();}//*******************************************************************////随机调换所有的子图像序列的位置,用于在 Splite image中显示//*******************************************************************//void Randarrary( vector<Mat>& vectorMat){for(int i=0;i<vectorMat.size();i++){srand(int(time(0)));int a=rand()%(vectorMat.size()-i)+i;swap(vectorMat[i],vectorMat[a]);}}//*******************************************************************////鼠标回调函数,用于获取需要查找的子图像在原图像中的位置,并在叠加显示在目标图像中//*******************************************************************//void OnMouseAction(int event,int x,int y,int flags,void *ustc){if(event==CV_EVENT_LBUTTONDOWN){Mat RoiSpilte,RoiSource;int rows=(y/Roirows)*Roirows;int clos=(x/Roicols)*Roicols;RoiSpilte=Spilteimage(Rect(clos,rows,Roicols,Roirows));imshow("Slice",RoiSpilte);Mat image=Mat::zeros(Sourceimage.rows-Roirows,Sourceimage.cols-Roicols,CV_32FC1);matchTemplate(Sourceimage,RoiSpilte,image,1);normalize(image,image,0,1,NORM_MINMAX);double minV=0;double maxV=0;Point minP,maxP;minMaxLoc(image,&minV,&maxV,&minP,&maxP);Mat ROIDst=Dstimage(Rect(minP.x,minP.y,Roicols,Roirows));addWeighted(ROIDst,0,RoiSpilte,1,0,ROIDst,-1);imshow("Jigsaw image",Dstimage);}}
资源文件和Code也可以在点击这里 拼图板小游戏 免积分下载
0 0
- 90年代经典“手游”—拼图板小游戏Opencv实现
- 16格拼图板网页版
- 贪吃蛇小游戏—C++、Opencv编写实现
- 品味昨日的经典-90年代经典老歌
- 经典小游戏2048C++的console实现
- 《创世之战》多途径隆重封测 重度手游年代敞开
- 经典小游戏——坦克大战
- 贪吃蛇——C++经典小游戏
- SEO不再是拼技术而是来到拼运营的年代了
- **图板优化**
- 【转】【经典】js小游戏
- JavaScript经典小游戏
- 经典贪吃蛇小游戏
- js经典赛车小游戏
- 汉字首拼实现
- 我们的年代《音乐天堂》经典回顾
- 程序员穿越 90年代
- 54部经典国外动画片:送给70-80年代的朋友 90年代后的一边画圈圈去41-50
- eclipse启动错误【看最后一句话就行】
- my ping tool
- hdu 5750 Dertouzos(数论:质数枚举)
- Java——类的继承
- 闭包的潜在用处
- 90年代经典“手游”—拼图板小游戏Opencv实现
- SqlDateTime 溢出。必须介于 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM之间的解决办法
- me 常用的的java编程规范
- 越客会议签到管理软件的身份证签到演示视频
- 深入体会__cdecl与__stdcall
- 浅谈UIScrollView上拉抽屉视图制作
- 二进制位相关知识
- centos7 JDK1.7&&MYSQL5.7安装
- 逆天了,浏览器里面竟然也能运行Linux(JSLinux)