作者:FPGA入门到精通
图像的镜像变换是图像处理中一种基本的几何变换操作,它涉及将图像沿着一个或多个坐标轴进行翻转。
本文将详细介绍图像镜像算法的基本原理、Python实现以及FPGA实现。
一、图像镜像算法知识
图像镜像算法包括水平镜像、垂直镜像和对角镜像。
下面的数学计算,均以图像的左上角顶点为原点,图像的宽为W,图像的高为H,设原始图像的任意点为P0(x0,y0),变换后的新点为P(x,y),记w = W - 1,h = H -1。
注意数学公式里,为什么是H-1、W-1?,因为图像的原点是(0, 0),即都是从0开始。
1、水平镜像
在水平镜像变换中,图像的每个点关于y轴(即垂直轴)进行翻转。
变换后,图像的左半部分和右半部分互为镜像。
用数学公式表示,则变换式为
y = y0、x = w - x0
矩阵变换公式为
2、垂直镜像
与水平镜像相对,垂直镜像变换是将图像的每个点关于x轴(即水平轴)进行翻转。
变换后,图像的上半部分和下半部分互为镜像。
用数学公式表示,则变换式为
y = h -y0、x = x0
矩阵变换公式为
3、对角镜像
对角镜像变换同时沿着x轴和y轴翻转图像,也就水平垂直镜像。
变换后,图像的每个点都将映射到其关于图像中心点对称的位置。
用数学公式表示,则变换式为
y = h -y0、x = w - x0
矩阵变换公式为
二、Python实现
直接调用矩阵运算变换即可实现。
1、源代码
import cv2 import numpy as np img = cv2.imread('test1.png') h, w, c = img.shape fliped_x_image = np.zeros((h, w, 3), dtype=np.uint8) fliped_y_image = np.zeros((h, w, 3), dtype=np.uint8) fliped_xy_image = np.zeros((h, w, 3), dtype=np.uint8) # 水平镜像 flip_matrix = np.array([[-1, 0, 0], [0, 1, 0], [w - 1, 0, 1]]) for y in range(h): for x in range(w): flip_x, flip_y, _ = np.dot([x, y, 1], flip_matrix) fliped_x_image[flip_y, flip_x] = img[y, x] # 垂直镜像 flip_matrix = np.array([[1, 0, 0], [0, -1, 0], [0, h - 1, 1]]) for y in range(h): for x in range(w): flip_x, flip_y, _ = np.dot([x, y, 1], flip_matrix) fliped_y_image[flip_y, flip_x] = img[y, x] # 对角镜像 flip_matrix = np.array([[1, 0, 0], [0, -1, 0], [0, h - 1, 1]]) for y in range(h): for x in range(w): flip_x, flip_y, _ = np.dot([x, y, 1], flip_matrix) fliped_xy_image[flip_y, flip_x] = img[y, x] # 显示图像 cv2.namedWindow("orignal", 0) cv2.resizeWindow("orignal", 300, 180) # 设置窗口大小 cv2.namedWindow("hor_flip", 0) cv2.resizeWindow("hor_flip", 300, 180) # 设置窗口大小 cv2.namedWindow("ver_flip", 0) cv2.resizeWindow("ver_flip", 300, 180) # 设置窗口大小 cv2.namedWindow("diag_flip", 0) cv2.resizeWindow("diag_flip", 300, 180) # 设置窗口大小 cv2.imshow('orignal', img) cv2.imshow('hor_flip', fliped_x_image) cv2.imshow('ver_flip', fliped_y_image) cv2.imshow('diag_flip', fliped_xy_image) cv2.waitKey(0) cv2.destroyAllWindows()
2、测试结果图像
三、FPGA实现
FPGA实现镜像变换算法,需要使用行缓存和帧缓存,从缓存中读取数据时,按照变换公式,计算读地址逻辑即可,这里分享下FPGA设计思路。
1、水平镜像
水平镜像,只涉及水平方向的数据顺序变换,只需要两个行缓存即可实现,读取地址不是顺序的,只能使用BRAM或URAM资源实现。
关键逻辑:乒乓操作,使用两个行缓存,写入数据时,按照一行数据从左到右依次写入,读取数据时,按照从右到左的逆序读数据即可。
源码暂不分享,可以看下FPGA实现效果:
2、垂直镜像
垂直镜像,涉及垂直方向的数据顺序变换,需要两个帧缓存即可实现,可以使用DDR实现。
关键逻辑:乒乓操作,使用两个帧缓存,写入数据时,按照从上到下依次写入每行数据,读取数据时,按照从下到上逆序读取每行数据。
源码暂不分享,可以看下FPGA实现效果:
3、对角镜像
对角镜像,涉及垂直方向和水平方向的数据顺序变换,只需要两个帧缓存即可实现,可以使用DDR实现。
关键逻辑:乒乓操作,使用两个帧缓存,写入数据时,按照从上到下依次写入每行数据,读取数据时,按照从下到上逆序读取每行数据,而且读取每行数据时,都是按照从右到左的顺序读取。
源码暂不分享,可以看下FPGA实现效果: