前言
最近在学校上了一门《数字图像处理》的课程,要求做一个实验,用很多小图像拼接成一张大图,类似与下面这种效果:
图是在网上找的,可以看到图中的小人其实是由很多的小图片组成的,课程要求就是作出这种效果的图片。
下面放出我做的成果图片:
处理之后:
程序还不是很完善,上面这种图颜色很单纯,没有特别多的细节变化,而一旦处理细节丰富的图像就成了下面的效果:
原图:
处理之后:
让我想起了梵高… …
程序还是不完善,,以后再改进算法,热切希望各位能补充改进意见。
下面进入主题。
开发环境
系统:Ubuntu 16.04。
语言:C++。
图形处理库:openCV。
前期配置
首先要安装openCV图形库,至于windows10系统上怎么安装我还没有看,课本上有讲解,可以自己看,我只说Ubuntu上的安装。
一、下载openCV源码
到openCV的官网中下载Linux版本的opencv。
我下载的是VERSION 3.1 OpenCV for Linux/Mac,网速有点慢,请耐心等待。
下载完毕会得到一个zip包,解压得到opencv-3.1.0文件夹,里面有这些东西:
图里面的build目录是没有的,这是我后来添加的,目前不要管它。
二、预先安装一些软件
sudo apt-get install build-essential cmake libgtk2.0-dev pkg-config python-dev python-numpy libavcodec-dev libavformat-dev libswscale-dev
不安装这些是跑不起来的。
三、编译openCV源码
进入opencv-3.1.0,建立build文件夹,然后编译
# mkdir build
# cd build
# cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
估计会编译20分钟左右,
四、安装openCV
编译完成后还是在build文件夹下,执行安装程序
# make install
如果最后显示有什么错误的话,很有可能是之前的步骤哪里输入错误了,重新来一遍试试。
五、测试
在其他地方建立一个文件夹test,写一个demo。
具体流程是这样的,你的新建立一个文件夹test,在里面创建main.cpp文件和CMakeLists.txt文件。main.cpp文件中引入openCV库:
// main.cpp
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main() {
Mat image = imread("你的图片的路径");
if (!image.data) {
cout << "read image file fail!" << endl;
}
namedWindow("Image");
imshow("Image", image);
}
CMakeLists.txt这样写
cmake_minimum_required(VERSION 3.5)
project(HandleImage)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(HandleImage ${SOURCE_FILES})
find_package(OpenCV REQUIRED)
target_link_libraries(HandleImage ${OpenCV_LIBS})
然后在这个文件夹test下执行命令
# cmake .
# make
如果前面没有错误的话,最后会在test目录下生成一个HandleImage可执行文件,运行它:
# ./HandleImage
算法思路
我们手头有一张原图和许多张小图片,我们要将这些小图片组合起来,使组合后的图像看起来像原图。
最终的图像是分成一块一块的,问题在于如何确定每一块对应哪一张小图片。我选择的是利用像素的RGB值来确定,思路如下:
1、如果我要替换原图中一个15 × 15的像素块,那么取出这个块中所有像素点的R、G、B的值,分别求和取平均,最后得到的R、G、B三个值就作为这个像素块的RGB代表。
2、由于所有的小图片都要转化成15 × 15的像素块,所以必须先将小图片进行放缩到15px × 15px,然后在用和上面相同的方法得到代表这个小图片的RGB值,这样每个小图片都会有一个自己的RGB值,我们会将它存储起来(暂时不考虑多个小图片RGB值相同的情况)。
3、求原图中15 × 15像素块的RGB值与每个小图片的RGB的差值。公式如下
int total = |原图片R值 - 小图片R值| + |原图片G值 - 小图片G值| + |原图片B值 - 小图片B值|
这样得到了两者之间的偏差。由于原图会和所有的小图片进行比较,所以我们可以找到所有的比较之中偏差最小的小图片对这个块进行填充。
源代码
因为是在设计上交前一天做的,有点匆忙,所以代码只是实现了功能,完全没有考虑到可读性和代码设计,以后有机会会慢慢修改。
源代码托管在github上,网址:https://github.com/PhoenixDefender/HandleImage
项目中的README.md文件会有代码的使用说明,如果你是windows系统就得修改一下源代码才能运行。
(PS:算法需要优化,求大神指点,感激不尽。)
这篇博客介绍了如何利用C++和OpenCV库,通过计算像素RGB值的偏差,将多张小图片拼接成一张大图。作者分享了在Ubuntu 16.04系统上的开发环境配置、OpenCV的安装和编译过程,以及算法思路和源代码。最终展示了实验结果,并表示程序还有待优化和完善。
443





