利用opencv实现九宫格拼图功能@TOC

- 设计思路

1 读入一张图片,并对图像进行切割,分成九块;
2 利用数组保存九张图片,设法将九张图片显示在一张图片中;
3 随机初始化,使九张图片随机分布在显示界面图片的九个区域;
4 利用鼠标回调函数,通过鼠标点击交换两张相邻图片的位置;

- 关于实现

1. 读入图片并对图片进行切割-------Rect()函数

  Rect(int _x,int _y,int _width,int _height); 参数意思为:左上角x坐标 左上角y坐标 矩形的宽 矩形的高
    Mat img = imread("C:\\picture\\aa.jpg");int m = img.cols;//宽int n = img.rows;//高Mat imge[10];imge[1] = img(Rect(0, 0, m / 3, n / 3));imge[2] = img(Rect(m / 3, 0, m / 3, n / 3));imge[3] = img(Rect(m / 3 * 2, 0, m / 3, n / 3));imge[4] = img(Rect(0, n / 3, m / 3, n / 3));imge[5] = img(Rect(m / 3, n / 3, m / 3, n / 3));imge[6] = img(Rect(m / 3 * 2, n / 3, m / 3, n / 3));imge[7] = img(Rect(0, n / 3 * 2, m / 3, n / 3));imge[8] = img(Rect(m / 3, n / 3 * 2, m / 3, n / 3));imge[9] = img(Rect(m / 3 * 2, n / 3 * 2, m / 3, n / 3));

图像布局

y x 1 2 3
1 1 2 3
2 4 5 6
3 7 8 9

2 九张图片显示在一张图片中------resize()函数

resize函数其实是调整大小的,但我们尝试一下发现,其实也可以用它来实现图片的“粘贴”功能
关于resize函数的用法如下

函数原型

void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR)

参数含义
src - 原图
dst - 目标图像。当参数dsize不为0时,dst的大小为size;否则,它的大小需要根据src的大小,参数fx和fy决定。dst的类型(type)和src图像相同
dsize - 目标图像大小。当dsize为0时,它可以通过以下公式计算得出:

所以,参数dsize和参数(fx, fy)不能够同时为0
fx - 水平轴上的比例因子。当它为0时,计算公式如下:

interpolation - 插值方法。共有5种:
1)INTER_NEAREST - 最近邻插值法
2)INTER_LINEAR - 双线性插值法(默认)
3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。
4)INTER_CUBIC - 基于4x4像素邻域的3次插值法
5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
借鉴博文
原文:https://blog.csdn.net/u012005313/article/details/51943442

将combine分区
cv::Mat combine = cv::Mat::zeros(m, n, img.type());
Mat imgROI1 = combine(Rect(0, 0, m / 3, n / 3));
Mat imgROI2 = combine(Rect(m / 3, 0, m / 3, n / 3));
Mat imgROI3 = combine(Rect(m / 3 * 2, 0, m / 3, n / 3));
Mat imgROI4 = combine(Rect(0, n / 3, m / 3, n / 3));
Mat imgROI5 = combine(Rect(m / 3, n / 3, m / 3, n / 3));
Mat imgROI6 = combine(Rect(m / 3 * 2, n / 3, m / 3, n / 3));
Mat imgROI7 = combine(Rect(0, n / 3 * 2, m / 3, n / 3));
Mat imgROI8 = combine(Rect(m / 3, n / 3 * 2, m / 3, n / 3));
Mat imgROI9 = combine(Rect(m / 3 * 2, n / 3 * 2, m / 3, n / 3));
//combine图片即为显示图片,将其分成九个区域//将图片a[1]至a[9]"粘贴"到combine的九个区域中
resize(a[1], imgROI1, imgROI1.size());
resize(a[2], imgROI2, imgROI2.size());
resize(a[3], imgROI3, imgROI3.size());
resize(a[4], imgROI4, imgROI4.size());
resize(a[5], imgROI5, imgROI5.size());
resize(a[6], imgROI6, imgROI6.size());
resize(a[7], imgROI7, imgROI7.size());
resize(a[8], imgROI8, imgROI8.size());
resize(a[9], imgROI9, imgROI9.size());

3 随机初始化九张图片的位置

新建图片数组a[],a[1]–a[9]随机存储imge的九张图片,将a[1]–a[9]顺序粘贴在九个区域中,即可随机初始化九张图片的位置。
代码实现:

//生成随机数int i, j;int b[10];//存储获取到的随机数。int f[10] = { 0 };//存储是否获取到过。int nx = 1; //计数器。srand((unsigned)time(NULL));//设置随机数种子。while (nx < 10){int my = rand() % 10; //获取一个0~9的随机数。if (f[my]||my==0) continue;//该数之前已经获取到过。b[nx++] = my;//将该数存入数组。f[my] = 1;//标记该数已经获取过。}for (i = 1; i <= 9; i++){a[i] = imge[b[i]];}

4 利用鼠标回调函数交换两张不相邻图片的位置

思路:
1 由鼠标位置坐标得知所点击区域是几
2 明确是第几次点击,以此判断我所要交换的第一二张图片
3 设置中间变量,利用数组交换两张图片的位置
4 交换前需要判断两张图片是否相邻

关于鼠标回调函数

opencv中的鼠标响应的函数是setMouseCallback()。

c++: void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)

winname:窗口的名字
onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param);
userdate:传给回调函数的参数

void on_Mouse(int event, int x, int y, int flags, void* param);

event是 CV_EVENT_*变量之一
EVENT_MOUSEMOVE 滑动
EVENT_LBUTTONDOWN 左击
EVENT_RBUTTONDOWN 右击
EVENT_MBUTTONDOWN 中键点击
EVENT_LBUTTONUP 左键放开
EVENT_RBUTTONUP 右键放开
EVENT_MBUTTONUP 中键放开
EVENT_LBUTTONDBLCLK 左键双击
EVENT_RBUTTONDBLCLK 右键双击
EVENT_MBUTTONDBLCLK 中键双击
x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系)
flags是CV_EVENT_FLAG的组合,flag的状态有:
EVENT_FLAG_LBUTTON 左键拖拽
EVENT_FLAG_RBUTTON 右键拖拽
EVENT_FLAG_MBUTTON 中键拖拽
EVENT_FLAG_CTRLKEY 按住Ctrl不放
EVENT_FLAG_SHIFTKEY 按住Shift不放
EVENT_FLAG_ALTKEY 按住Alt不放
param是用户定义的传递到setMouseCallback函数调用的参数。

参照原文:https://blog.csdn.net/roly_yu/article/details/44623739

判断所点击图片的位置—利用鼠标位置(x,y)
//可参照上方表格
int f(int xx, int yy)
{int s;if (xx + yy == 2){s = 1;}if (xx + yy == 3 && xx > yy){s = 2;}if (xx + yy == 4 && xx > yy){s = 3;}if (xx + yy == 3 && xx < yy){s = 4;}if (xx + yy == 4 && xx == yy){s = 5;}if (xx + yy == 5 && xx > yy){s = 6;}if (xx + yy == 4 && xx < yy){s = 7;}if (xx + yy == 5 && xx < yy){s = 8;}if (xx + yy == 6){s = 9;}return s;
}
void onMouseHandle(int event, int x, int y, int flags, void *param)
{int xx ;int yy ;switch (event){case CV_EVENT_LBUTTONDOWN ://左键单击{ xx = x / (m / 3) + 1;yy = y / (n / 3) + 1;++t;if (t % 2 == 1){first = f(xx, yy);}if (t % 2 == 0){second = f(xx, yy);if (second == first + 3 || second == first - 3 || second == first + 1 || second == first - 1){temp = a[first];a[first] = a[second];a[second] = temp;resize(a[1], imgROI1, imgROI1.size());resize(a[2], imgROI2, imgROI2.size());resize(a[3], imgROI3, imgROI3.size());resize(a[4], imgROI4, imgROI4.size());resize(a[5], imgROI5, imgROI5.size());resize(a[6], imgROI6, imgROI6.size());resize(a[7], imgROI7, imgROI7.size());resize(a[8], imgROI8, imgROI8.size());resize(a[9], imgROI9, imgROI9.size());}}imshow("九宫格", combine);}break;default:break;}}

效果展示

全部代码
#include <iostream>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <stdlib.h>#include <time.h> using namespace cv;
using namespace std;Mat img = imread("C:\\picture\\aa.jpg");
int m = img.cols;//宽
int n = img.rows;//高
cv::Mat combine = cv::Mat::zeros(m, n, img.type());
Mat imgROI1 = combine(Rect(0, 0, m / 3, n / 3));
Mat imgROI2 = combine(Rect(m / 3, 0, m / 3, n / 3));
Mat imgROI3 = combine(Rect(m / 3 * 2, 0, m / 3, n / 3));
Mat imgROI4 = combine(Rect(0, n / 3, m / 3, n / 3));
Mat imgROI5 = combine(Rect(m / 3, n / 3, m / 3, n / 3));
Mat imgROI6 = combine(Rect(m / 3 * 2, n / 3, m / 3, n / 3));
Mat imgROI7 = combine(Rect(0, n / 3 * 2, m / 3, n / 3));
Mat imgROI8 = combine(Rect(m / 3, n / 3 * 2, m / 3, n / 3));
Mat imgROI9 = combine(Rect(m / 3 * 2, n / 3 * 2, m / 3, n / 3));
Mat a[10];
Mat imge[10];
int t = 0;
int first;
int second;
Mat temp;int f(int xx, int yy);
void onMouseHandle(int event, int x, int y, int flags, void *param);int main(){//分割图像rect()imge[1] = img(Rect(0, 0, m / 3, n / 3));imge[2] = img(Rect(m / 3, 0, m / 3, n / 3));imge[3] = img(Rect(m / 3 * 2, 0, m / 3, n / 3));imge[4] = img(Rect(0, n / 3, m / 3, n / 3));imge[5] = img(Rect(m / 3, n / 3, m / 3, n / 3));imge[6] = img(Rect(m / 3 * 2, n / 3, m / 3, n / 3));imge[7] = img(Rect(0, n / 3 * 2, m / 3, n / 3));imge[8] = img(Rect(m / 3, n / 3 * 2, m / 3, n / 3));imge[9] = img(Rect(m / 3 * 2, n / 3 * 2, m / 3, n / 3));//生成随机数int i, j;int b[10];//存储获取到的随机数。int f[10] = { 0 };//存储是否获取到过。int nx = 1; //计数器。srand((unsigned)time(NULL));//设置随机数种子。while (nx < 10){int my = rand() % 10; //获取一个0~9的随机数。if (f[my]||my==0) continue;//该数之前已经获取到过。b[nx++] = my;//将该数存入数组。f[my] = 1;//标记该数已经获取过。}for (i = 1; i <= 9; i++){a[i] = imge[b[i]];}namedWindow("九宫格");resize(a[1], imgROI1, imgROI1.size());resize(a[2], imgROI2, imgROI2.size());resize(a[3], imgROI3, imgROI3.size());resize(a[4], imgROI4, imgROI4.size());resize(a[5], imgROI5, imgROI5.size());resize(a[6], imgROI6, imgROI6.size());resize(a[7], imgROI7, imgROI7.size());resize(a[8], imgROI8, imgROI8.size());resize(a[9], imgROI9, imgROI9.size());imshow("九宫格", combine);setMouseCallback("九宫格", onMouseHandle, (void*)&combine);// 等待6000 ms后窗口自动关闭waitKey(0);return 0;}int f(int xx, int yy)
{int s;if (xx + yy == 2){s = 1;}if (xx + yy == 3 && xx > yy){s = 2;}if (xx + yy == 4 && xx > yy){s = 3;}if (xx + yy == 3 && xx < yy){s = 4;}if (xx + yy == 4 && xx == yy){s = 5;}if (xx + yy == 5 && xx > yy){s = 6;}if (xx + yy == 4 && xx < yy){s = 7;}if (xx + yy == 5 && xx < yy){s = 8;}if (xx + yy == 6){s = 9;}return s;
}
void onMouseHandle(int event, int x, int y, int flags, void *param)
{int xx ;int yy ;switch (event){case CV_EVENT_LBUTTONDOWN ://左键单击{ xx = x / (m / 3) + 1;yy = y / (n / 3) + 1;++t;if (t % 2 == 1){first = f(xx, yy);}if (t % 2 == 0){second = f(xx, yy);if (second == first + 3 || second == first - 3 || second == first + 1 || second == first - 1){temp = a[first];a[first] = a[second];a[second] = temp;resize(a[1], imgROI1, imgROI1.size());resize(a[2], imgROI2, imgROI2.size());resize(a[3], imgROI3, imgROI3.size());resize(a[4], imgROI4, imgROI4.size());resize(a[5], imgROI5, imgROI5.size());resize(a[6], imgROI6, imgROI6.size());resize(a[7], imgROI7, imgROI7.size());resize(a[8], imgROI8, imgROI8.size());resize(a[9], imgROI9, imgROI9.size());}}imshow("九宫格", combine);}break;default:break;
}
}

利用opencv实现九宫格拼图功能相关推荐

  1. python基于opencv的手势识别_怎么在Python3.5 中利用OpenCV实现一个手势识别功能

    怎么在Python3.5 中利用OpenCV实现一个手势识别功能 发布时间:2020-12-22 11:56:32 来源:亿速云 阅读:67 作者:Leah 怎么在Python3.5 中利用OpenC ...

  2. 利用openCV实现中值滤波自定义滤波窗口尺寸的功能(类似halcon中的median_rect函数功能)

    利用openCV实现中值滤波自定义滤波窗口尺寸的功能(类似halcon中的median_rect函数功能) 在halcon图像库中有一个常用的中值滤波算子median_rect: median_rec ...

  3. 利用opencv库录制九宫格视频(C++实现)

    利用opencv库录制九宫格视频(C++实现) 在项目开始之前,我的环境已配置完成,具体环境如何配置可参考网络教程.下面我们开始项目的实现 库的导入 #include<iostream> ...

  4. VB实现可调节难度的九宫格拼图

    #VB实现可调节难度的九宫格拼图 实现本游戏需要熟练掌握paintpicture函数的应用,如果读者对该函数不熟练,需要读一下前面两篇博客哦 http://blog.csdn.net/wf824284 ...

  5. 利用OpenCV、Python和Ubidots构建行人计数器程序(附完整代码)

    作者 | Jose Garcia 译者 | 吴振东 校对 | 张一豪.林亦霖,编辑 | 于腾凯 来源 | 数据派(ID:datapi) 导读:本文将利用OpenCV,Python和Ubidots来编写 ...

  6. python中import cv2遇到的错误及安装方法_独家利用OpenCV,Python和Ubidots来构建行人计数器程序(附代码amp;解析)...

    作者:Jose Garcia 翻译:吴振东 校对:张一豪 本文约4000字,建议阅读14分钟. 本文将利用OpenCV,Python和Ubidots来编写一个行人计数器程序,并对代码进行了较为详细的讲 ...

  7. 图像处理中,SIFT,FAST,MSER,STAR等特征提取算法的比较与分析(利用openCV实现)

    图像处理中,SIFT,FAST,MSER,STAR等特征提取算法的比较与分析(利用openCV实现) 本文实验为自己原创,转载请注明出处. 本人为研究生,最近的研究方向是物体识别.所以就将常用的几种特 ...

  8. AI 质检学习报告——实践篇——第一步:python利用OpenCV打开摄像头并截图

    写在前边 想要做一个AI质检的项目,一点一点来,首先:python利用OpenCV打开摄像头并拍照. 效果 设摄像头像素不咋地,实际的产品肯定不会是这个像素,必须安排一个专业的. 实现代码 impor ...

  9. 利用OpenCV实现人脸检测

    如何在一副图片中检测到人脸,这涉及到计算机图形学中一些非常复杂的计算,如果这些计算都靠程序员自己来编程,那么工作量就相当大.OpenCV全称是Open Computer Vision,是指开放的计算机 ...

  10. html整体图片拆分拼图代码源代码,canvas拼图功能实现代码示例

    最近做项目的时候遇到照片拼图的功能,便在这里分享自己的封装的canvas拼图功能,可能代码写的不好,如果有疑问或者是有更好的方法的,可以私聊我,或者是评论指出,感谢各位 实现的思路其实挺简单的,主要是 ...

最新文章

  1. select,poll,epoll区别。
  2. 线程池ThreadPoolExcutor
  3. 汽车需要镀晶吗?镀晶是起什么作用的?
  4. mysql 修改配置生效_MySQL修改my.cnf配置不生效的解决方法
  5. Unity 协程原理探究与实现
  6. Java PropertyPermission equals()方法与示例
  7. 数据可视化【十】绘制地图
  8. 聚类(Clustering): K-means算法
  9. 为什么有那么多人选择“人工智能”,真的有那么好吗?
  10. django之上传图片
  11. wpewebkit在ubuntu18.04上编译配置
  12. Android打开系统文件管理器
  13. 思聪吃热狗(双人版)
  14. 波的散射,孔金瓯等著三卷本书籍目录
  15. 线性代数 --- 投影与最小二乘 上(一元一次方程组的最小二乘解与向量在一维子空间上的投影)
  16. Python人脸图像特征提取(HOG、Dlib、CNN方法)
  17. Docker国内镜像地址和下载安装
  18. Elasticsearch清理历史索引笔记
  19. 60/68/70/73/78MM船用锚链现货供应-中运锚链
  20. 0040__node.js中Express简介

热门文章

  1. 如何扩展关键词,以及使用python多线程爬取bing搜索结果
  2. 蚂蚁分类信息系统伪静态多城市版nginx规则自适应URL
  3. Saas平台接入商户代小程序开发解决方案
  4. java 判断exception类型_Java中获取Exception的详细信息
  5. 齐齐哈尔大学计算机调剂,齐齐哈尔大学2020年硕士研究生调剂信息
  6. banner图片不拉伸、全屏宽、居中显示的方法
  7. JavaScript if...else 语句
  8. 安农大计算机专业录取分数线,安徽农业大学+录取分数线
  9. matlab百分号是什么意思,matlab 两个百分号
  10. 怎么理解“不经审视的人生,不值得过!“