1、QT 实现图 像处理-傅立叶变换、傅立叶反变换、平滑、锐化与模板匹配 实验环境:1,Linux操作系统2,QT3 编程开发环境3,C+编程语言傅立叶变换和傅立叶反变换1.1. 主要源代码readImage() 从图像中读取数据writeImage() 往图像中写入数据fft() 快速傅立叶变换ifft() 快速傅立叶反变换adjustImageSize() 调整图像大小fourier() 傅立叶变换ifourier() 傅立叶反变换 1.1.1 从图像中读取数据 void ImageProcess:readImage(complex data, const QImage /数据首地址 int
2、depth = srcImage.depth(); /每个像素的bit 数 int lineBytes = srcImage.bytesPerLine(); /每行的字节数 int w = srcImage.width(); /宽 int h = srcImage.height(); /高 byte *pByte; /遍历读取每个像素,并转换为灰度值 int i, j; for(i = 0; i ( *pByte, 0); else if(32 = depth)/32 位表示,数据格式为0xFFBBGGRR或 0xAABBGGRR pByte = pImageBytes + i * lineB
3、ytes + j * 4; /根据 RGB模式转化成 YIQ 色彩模式的方式,取 Y 作为灰 度值 byte pixelValue = (byte)(0.299 * (float)pByte0 + 0.587 * (float)pByte1 + 0.114 * (float)pByte2); datai * w + j = complex( pixelValue, 0); else cout data, double coef) int lineBytes = destImage.bytesPerLine(); int depth = destImage.depth(); int w = de
4、stImage.width(); int h = destImage.height(); byte *pImageBytes = destImage.bits(); byte *pByte; for(int i = 0; i 255 ? 255 : spectral; /根据图像格式写数据 if(8 = depth) pByte = pImageBytes + i * lineBytes + j; *pByte = spectral; else if(32 = depth) pByte = pImageBytes + i * lineBytes + j * 4; pByte0 = pByte1
5、 = pByte2 = spectral; else return; 1.1.3 递归形式的快速傅立叶变换 /数组 a 为输入,数组 y 为输 出,2 的 power 次方为数组的长度 void ImageProcess:fft(const complex a, complex y, int power) if(0 = power) y0 = a0; return; int n = 1 wn(cos(angle), sin(angle); complex w(1, 0); complex *a0 = new complexn / 2; complex *a1 = new complexn /
6、2; complex *y0 = new complexn / 2; complex *y1 = new complexn / 2; for(int i = 0; i u; for(int k = 0; k y, complex a, int power) int count = 1 *x = new complexcount; memcpy(x, y, sizeof(complex) * count); int i; for(i = 0; i (xi.real(), -xi.imag(); /共轭复数 fft(x, a, power); /调用快速傅 立叶变换算法 for(i = 0; i
7、(ai.real() / count, -ai.imag() / count); /共轭复数 delete x; 1.1.5 调整图像的大小 /宽和高都截取为 2 的指数倍 void ImageProcess:adjustImageSize(QImage int h = 1; int width = image.width(); int height = image.height(); wp = 0, hp = 0; while(w * 2 w * h; readImage(currentImageData, currentImage); /读取数据 else if(NULL = curren
8、tImageData) currentImageData = new complexw * h; readImage(currentImageData, currentImage); /读取数据 w = currentImage.width(); /更新宽和高 h = currentImage.height(); complex *TD = currentImageData; /当前读取的数据为时域 complex *FD = new complexw * h; /申请空间保存变换结果 int i, j; for(i = 0; i ) * w * h); complex *columnt =
9、new complexh; complex *columnf = new complexh; for(i = 0; i setPixmap(QPixmap(currentImage); 1.1.7 傅立叶反变换 傅立叶反变换的思想与傅立叶变化相似,只是时域和频域互换,然后调用快速傅立叶反变换 ifft 而不是快速傅立叶变换 fft。 1.2. 运行截图1.2.1 正方形 输入一个 256*256 的图形,背景为白色,中间有一黑色的正方形,如图 1-1 所示。经过傅立叶变换后的结果如图 1-2 所示(注:没有采用平移到中心的方法)。 图 1-1 图 1-2 1.2.2 旋转 45 度 将图 1-
10、1 旋转 45度后的输入 如图 1-3 所示。其傅立叶变换结果如图1-4 所示。 图 1-3 图 1-4 1.2.3 输入长方形图像 输入图像如图 1-5 所示。傅立叶变换结果如图 1-6 所示。 图 1-5 图 1-6 1.2.4 傅立叶反变换 对傅立叶变换结果图 1-2 进行傅立叶反变换,其结果与原图 1-1 相同,如图 1-7 所示: 图 1-7 图像增强图像增强是一种很重要的图像处理技术,为了方便人们观察以及机器处理而去处理给定的一幅图像。有很多图像增强的方法,以下这部分实现了其中的平滑和锐化这两种方法。 2.1. 主要源码2.1.1 平滑 平滑采用的模板是 , 实现如下: void
11、ImageProcess:smooth() int w = currentImage.width(); int h = currentImage.height(); if(NULL = currentImageData) /判断是否需要重新读取数据 currentImageData = new complexw * h; readImage(currentImageData, currentImage); /拷贝一份数据便于计算 complex *buffer = new complexw * h; memcpy(buffer, currentImageData, sizeof(complex
12、) * w * h); /根据模板进行计算 /为了简化编码忽略了图像边界(i =0 or h, j =0 or w),对于整体效果没有影响 int i, j; for(i = 1; i k; k = buffer(i - 1) * w + j - 1; k += buffer(i - 1) * w + j; k += buffer(i - 1) * w + j + 1; k += bufferi * w + j - 1; k += bufferi * w + j; k += bufferi * w + j + 1; k += buffer(i + 1) * w + j - 1; k += bu
13、ffer(i + 1) * w + j; k += buffer(i + 1) * w + j + 1; k = complex(k.real() / 9, 0); currentImageDatai * w + j = k; writeImage(currentImage, currentImageData); pDispLabel-setPixmap(QPixmap(currentImage); 2.1.2 锐化 采用拉普拉斯锐化,其模板为 ,其实现如下: void ImageProcess:sharp() int w = currentImage.width(); int h = cur
14、rentImage.height(); if(NULL = currentImageData) /判断是否需要读取数据 currentImageData = new complexw * h; readImage(currentImageData, currentImage); /拷贝一份数据便于计算 complex *buffer = new complexw * h; memcpy(buffer, currentImageData, sizeof(complex) * w * h); /根据模板进行计算 /为了简化编码忽略了图像边界(i =0 or h, j =0 or w),对于整体效果
15、没有影响 int i, j; complex k; for(i = 1; i (k.real() * 5, 0); k -= buffer(i - 1) * w + j; k -= bufferi * w + j - 1; k -= bufferi * w + j + 1; k -= buffer(i + 1) * w + j; currentImageDatai * w + j = k; writeImage(currentImage, currentImageData); pDispLabel-setPixmap(QPixmap(currentImage); 2.2. 运行截图输入图像 2
16、-1,其平滑结果 为图 2-2,锐化结果为 图 2-3。 图 2-1 原来的图像 图 2-2 平滑后的图 像 图 2-3 锐化后的图 像 图像分析这部分主要实现了图像的模板匹配。模板匹配是一种非常原始的模式识别方法。有很多模板匹配的算法。这里采用的算法是计算二者之间的相似度,在目标图像中选取一个坐标,将以该坐标为左上角选定一块区域,计算该区域与模板的相似度,相似度最大的点即为匹配之处。通过二者之间的差异度来判断其相似程度,差异度的计算:m = 。即将累加其像素之间的差值,为了提高计算速度,可以设置阀值,当 m 大于阀值时,认定该块区域不匹配,继续寻找下一区域。 3.1. 主要源码void Im
17、ageProcess:match() /让用户选取模板 QString fileName = QFileDialog:getOpenFileName(“/home/tanqiyu“, “Images (*.png *.xpm .jpg)“, this, “open file dialog“, “Choose a model image“); if(QString:null = fileName) return; /读取模板数据 QImage modelImage(fileName); int mw = modelImage.width(); int mh = modelImage.height
18、(); complex *modelImageData = new complexmw * mh; readImage(modelImageData, modelImage); unsigned long t = mw * mh * 8; /根据匹配模板的大小设置一定的阀值 unsigned long m = t; /初始差异度 int ri = -1; /z 左上角坐标(ri, rj) int rj = -1; int w = currentImage.width(); int h = currentImage.height(); if(NULL = currentImageData) /判
19、断是否需要读取目标图像数据 currentImageData = new complexw * h; readImage(currentImageData, currentImage); /遍历目标图像,选取左上角坐标,考虑到模板图像的大小 注意不要越界 int i, j; for(i = 0; i = t) /判断是否大 于阀值 overFlag = true; if(k ri + mh - 1 | j rj + mw - 1) currentImageDatai * w + j = complex(255, 0); writeImage(currentImage, currentImageData); pDispLabel-setPixmap(QPixmap(currentImage); 3.2. 运行截图目标图像为图 3-1,图 3-2 位匹配模 板,匹配结果为图 3-3。 图 3-1 目标图像 图 3-2 匹配模板 匹配结果 宁静的水泡关注 - 0粉丝 - 0关注博主