• 2020-11-24 12:04:38

I would like to use python to perform a geometric transform over an image, to 'straighten' or rectify an image along a given curve. It seems that scikit-image ProjectiveTransform() and warp() are very good for this, but the documentation is sparse. I followed the documentation here, but I couldn't get it to work properly for a sample case.

Here's an example: I'll create an image with two concentric circles, and the goal is to rectify one quarter of these circles, so that the resulting image are two parallel lines. Here is the sample data:

import numpy as np

a = np.zeros((500, 500))

# create two concentric circles with a thickness of a few pixels:

for i in range(500):

for j in range(500):

r = np.sqrt((i - 250)**2 + (j - 250)**2)

if r > 50 and r < 52:

a[i, j] = 10

if r > 100 and r < 102:

a[i, j] = 10

# now create the coordinates of the control points in the original image:

(x0, y0) = (250, 250)

r = 30 # inner circle

x = np.linspace(250 - r, 250, 50)

y = np.sqrt(r ** 2 - (x - x0) ** 2) + x0

r2 = 120 # outer circle

x2 = np.linspace(250 - r2, 250, 50)

y2 = np.sqrt(r2 ** 2 - (x2 - x0) ** 2) + x0

dst = np.concatenate((np.array([x, y]).T, np.array([x2, y2]).T))

And this can be plotted, e.g.:

imshow(a, cmap='gist_gray_r')

plot(x, y, 'r.')

plot(x2, y2, 'r.')

So my goal is to rectify the image in the quadrant given by the red control points. (In this case, this is the same as a Cartesian to polar transformation.) Using scikit image from the documentation example, I've done:

# create corresponding coordinates for control points in final image:

xi = np.linspace(0, 100, 50)

yi = np.zeros(50)

xi2 = xi

yi2 = yi + (r2 - r)

src = np.concatenate((np.array([xi, yi]).T, np.array([xi2, yi2]).T))

# transform image

from skimage import transform, data

tform3 = transform.ProjectiveTransform()

tform3.estimate(src, dst)

warped = transform.warp(a, tform3)

I was expecting this warped image to show two parallel lines, but instead I get:

What am I doing wrong here?

Note that while in this case it is a Cartesian to polar transform, in the most general case I'm looking for a transformation from some arbitrary curve. If someone knows of a better way using some other package, please let me know. I can solve this problem by using ndimage.map_coordinates for a bunch of radial lines, but was looking for something more elegant.

解决方案

A ProjectiveTransform is a linear transformation, and cannot match your deformation scheme. There may be better options, but for arbitrary curves you can make it work with a PiecewiseAffineTransform, which will match anything you throw at it by tessellating linear transformations. If you simply change the name of the transform in your code, this is the output I get:

So you'll probably need to tweak it a little bit to get what you are after, but at least it produces the two parallel lines you were expecting in the area where your transformation is well defined.

更多相关内容
• 图像的平移 图像平移（Translation）是将图 像中所有的点都按照指定的平移量,进行水平、垂直移动。 x=self.trans.x y=self.trans.y # img[x:h-1,y:w-1]=image[0:h-1-x,0:w-1-y] for j in range(h): for i in ...

### 图像的平移

图像平移（Translation）是将图 像中所有的点都按照指定的平移量,进行水平、垂直移动。

x=self.trans.x
y=self.trans.y
# img[x:h-1,y:w-1]=image[0:h-1-x,0:w-1-y]
for j in range(h):
for i in range(w):
i0=i+x
j0=j+y
if(i0>=0) and (i0<w) and (j0>=0)and (j0<h):
img[j0,i0]=image[j,i]


### 图像镜像变换

图像的镜像变换分为两种：一种是水平镜像,另一种是垂直镜像。
图像的水平镜像操作是以原图像的垂直中轴线为中心，将图像分为左右两部分进行对称变换；
图像的垂直镜像操作是以原图像的水平中轴线为中心，将图像分为上下两部分进行对称变换。
镜像变换后图的高和宽都不变。

水平镜像

垂直镜像

   for j in range(h):
for i in range(w):
img[j,i]=image[j,w-1-i]
XImage.imShow(img, self.lb_2)

for j in range(h):
for i in range(w):
img[j, i] = image[h-1-j,i]
XImage.imShow(img, self.lb_2)


### 图像缩放

  image = self.image.xBitmap.img_org
h, w, c = image.shape
# 转置影响宽和高
ax = self.zoom.x
ay = self.zoom.y
aH = int(ay * h)
aW = int(ax * w)
out = np.zeros((aH, aW, c), dtype=np.uint8)
for y in range(aH):
for x in range(aW):
x0 = int(x / ax)
y0 = int(y / ay)
out[y, x] = image[y0, x0]
XImage.imShow(out, self.lb_2)


### 图像旋转

图像旋转必须指明图像绕着什么旋 转。一般图像的旋转是以图像的中心为原点，旋转一定的角度。 旋转后，一般会改变图像的大小。

# 绕中心的旋转
def rotate(self,img, angle):
H, W, C = img.shape
anglePi = angle * math.pi / 180.0
cosA = math.cos(anglePi)
sinA = math.sin(anglePi)
out = np.zeros((H, W, C), dtype=np.uint8)  # 必须是8 不然显示不出图像
for y in range(H):
for x in range(W):

x0 = int(cosA * x - sinA * y - 0.5 * W * cosA + 0.5 * H * sinA + 0.5 * W)
y0 = int(sinA * x + cosA * y - 0.5 * W * sinA - 0.5 * H * cosA + 0.5 * H)
if 0 < x0 < W and 0 < y0 < H:  # 计算结果是这一范围内的x0，y0才是原始图像的坐标。
out[y0, x0] = img[y, x]

return out

展开全文
• Python中的图像处理（第五章）Python图像几何变换（1）前言一. Python准备二. Python仿真三. 小结 前言 随着人工智能研究的不断兴起，Python的应用也在不断上升，由于Python语言的简洁性、易读性以及可扩展性，特别...

# 前言

随着人工智能研究的不断兴起，Python的应用也在不断上升，由于Python语言的简洁性、易读性以及可扩展性，特别是在开源工具和深度学习方向中各种神经网络的应用，使得Python已经成为最受欢迎的程序设计语言之一。由于完全开源，加上简单易学、易读、易维护、以及其可移植性、解释性、可扩展性、可扩充性、可嵌入性：丰富的库等等，自己在学习与工作中也时常接触到Python，这个系列文章的话主要就是介绍一些在Python中常用一些例程进行仿真演示！

本系列文章主要参考杨秀章老师分享的代码资源，杨老师博客主页是Eastmount，杨老师兴趣广泛，不愧是令人膜拜的大佬，他过成了我理想中的样子，希望以后有机会可以向他请教学习交流。

因为自己是做图像语音出身的，所以结合《Python中的图像处理》，学习一下Python，OpenCV已经在Python上进行了多个版本的维护，所以相比VS，Python的环境配置不会那么繁琐，缺什么库直接安装就可以。本系列文章例程都是基于Python3.8的环境下进行，所以大家在进行借鉴的时候建议最好在3.8.0版本以上进行仿真。本文继续来对本书第五章的4个例程进行介绍。

# 一. Python准备

如何确定自己安装好了python

win+R输入cmd进入命令行程序

点击“确定”

输入：python，回车

看到Python相关的版本信息，说明Python安装成功。

# 二. Python仿真

（1）新建一个chapter05_01.py文件，输入以下代码，图片也放在与.py文件同级文件夹下

#encoding:utf-8
#By:Eastmount CSDN 2021-02-01
import cv2
import numpy as np

#读取图片

#图像平移矩阵
M = np.float32([[1, 0, 100], [0, 1, 50]])

#获取原始图像列数和行数
rows, cols = src.shape[:2]

#图像平移
result = cv2.warpAffine(src, M, (cols, rows))

#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()



保存.py文件
输入eixt()退出python，输入命令行进入工程文件目录

输入以下命令，跑起工程

python chapter05_01.py


没有报错，直接弹出图片，运行成功！

（2）新建一个chapter05_02.py文件，输入以下代码，图片也放在与.py文件同级文件夹下

#encoding:utf-8
#By:Eastmount CSDN 2021-02-01
import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取图片
image = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

#图像平移
#垂直方向 向下平移100
M = np.float32([[1, 0, 0], [0, 1, 100]])
img1 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

#垂直方向 向上平移100
M = np.float32([[1, 0, 0], [0, 1, -100]])
img2 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

#水平方向 向右平移100
M = np.float32([[1, 0, 100], [0, 1, 0]])
img3 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

#水平方向 向左平移100
M = np.float32([[1, 0, -100], [0, 1, 0]])
img4 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

#循环显示图形
titles = [ 'Image1', 'Image2', 'Image3', 'Image4']
images = [img1, img2, img3, img4]
for i in range(4):
plt.subplot(2,2,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()



保存.py文件输入以下命令，跑起工程

python chapter05_02.py


没有报错，直接弹出图片，运行成功！

（3）新建一个chapter05_03.py文件，输入以下代码，图片也放在与.py文件同级文件夹下

#encoding:utf-8
#By:Eastmount CSDN 2021-02-01
import cv2
import numpy as np

#读取图片

#图像缩放
result = cv2.resize(src, (200,100))
print(result.shape)

#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()



保存.py文件输入以下命令，跑起工程

python chapter05_03.py


没有报错，直接打印缩放尺寸，弹出图片，运行成功！

（4）新建一个chapter05_04.py文件，输入以下代码，图片也放在与.py文件同级文件夹下

#encoding:utf-8
#By:Eastmount CSDN 2021-02-01
import cv2
import numpy as np

#读取图片
rows, cols = src.shape[:2]
print(rows, cols)

#图像缩放 dsize(列,行)
result = cv2.resize(src, (int(cols*0.6), int(rows*1.2)))

#显示图像
cv2.imshow("src", src)
cv2.imshow("result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()



保存.py文件输入以下命令，跑起工程

python chapter05_04.py


没有报错，直接打印行列数，弹出图片，运行成功！

# 三. 小结

本文主要介绍在Python中调用OpenCV库进行图片读取，以及图像的平移缩放，本书的介绍比较系统全面，所以会出一个系列文章进行全系列仿真实现，下一篇文章将继续介绍第五章节的仿真实例，感兴趣的还是建议去原书第五章深入学习理解。每天学一个Python小知识，大家一起来学习进步阿！

本系列示例主要参考杨老师GitHub源码，安利一下地址：ImageProcessing-Python（喜欢记得给个star哈！）

展开全文
• 主要介绍了Python实现图像几何变换的方法,实例分析了Python基于Image模块实现图像翻转、旋转、改变大小等操作的相关技巧,非常简单实用,需要的朋友可以参考下
• 欢迎大家来到“Python从...上一篇文章介绍图像几何变换，包括图像平移、图像缩放和图像旋转。这篇文章将继续讲解图像几何变换，包括图像镜像、图像仿射和图像透视。希望文章对您有所帮助，如果有不足之处，还请海涵。

欢迎大家来到“Python从零到壹”，在这里我将分享约200篇Python系列文章，带大家一起去学习和玩耍，看看Python这个有趣的世界。所有文章都将结合案例、代码和作者的经验讲解，真心想把自己近十年的编程经验分享给大家，希望对您有所帮助，文章中不足之处也请海涵。Python系列整体框架包括基础语法10篇、网络爬虫30篇、可视化分析10篇、机器学习20篇、大数据分析20篇、图像识别30篇、人工智能40篇、Python安全20篇、其他技巧10篇。您的关注、点赞和转发就是对秀璋最大的支持，知识无价人有情，希望我们都能在人生路上开心快乐、共同成长。

该系列文章主要讲解Python OpenCV图像处理和图像识别知识，前期主要讲解图像处理基础知识、OpenCV基础用法、常用图像绘制方法、图像几何变换等，中期讲解图像处理的各种运算，包括图像点运算、形态学处理、图像锐化、图像增强、图像平滑等，后期研究图像识别、图像分割、图像分类、图像特效处理以及图像处理相关应用。

上一篇文章介绍图像几何变换，包括图像平移、图像缩放和图像旋转。这篇文章将继续讲解图像几何变换，包括图像镜像、图像仿射和图像透视。希望文章对您有所帮助，如果有不足之处，还请海涵。

### 文章目录

下载地址：

前文赏析：

第一部分 基础语法

第二部分 网络爬虫

第三部分 数据分析和机器学习

第四部分 Python图像处理基础

第五部分 Python图像运算和图像增强

第六部分 Python图像识别和图像处理经典案例

第七部分 NLP与文本挖掘

第八部分 人工智能入门知识

第九部分 网络攻防与AI安全

第十部分 知识图谱构建实战

扩展部分 人工智能高级案例

作者新开的“娜璋AI安全之家”将专注于Python和安全技术，主要分享Web渗透、系统安全、人工智能、大数据分析、图像识别、恶意代码检测、CVE复现、威胁情报分析等文章。虽然作者是一名技术小白，但会保证每一篇文章都会很用心地撰写，希望这些基础性文章对你有所帮助，在Python和安全路上与大家一起进步。

# 一.图像镜像

图像镜像是图像旋转变换的一种特殊情况，通常包括垂直方向和水平方向的镜像。水平镜像通常是以原图像的垂直中轴为中心，将图像分为左右两部分进行堆成变换。如图7-1所示：

垂直镜像通常是以原图像的水平中轴线为中心，将图像划分为上下两部分进行堆成变换的过程，示意图如图7-2所示。

在Python中主要调用OpenCV的flip()函数实现图像镜像变换，函数原型如下：

• dst = cv2.flip(src, flipCode)
– src表示原始图像
– flipCode表示翻转方向，如果flipCode为0，则以X轴为对称轴翻转，如果fliipCode>0则以Y轴为对称轴翻转，如果flipCode<0则在X轴、Y轴方向同时翻转。

下面代码是实现三个方向的翻转。

# -*- coding:utf-8 -*-
# By：Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取图片
src = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

#图像翻转
img1 = cv2.flip(src, 0)   #参数=0以X轴为对称轴翻转
img2 = cv2.flip(src, 1)   #参数>0以Y轴为对称轴翻转
img3 = cv2.flip(src, -1)  #参数<0以X轴和Y轴翻转

#显示图形
titles = ['Source', 'Image1', 'Image2', 'Image3']
images = [src, img1, img2, img3]
for i in range(4):
plt.subplot(2,2,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()


输出结果如图7-3所示，图中“Source”为原始图像，“Image1”为以X轴为对称轴翻转或垂直镜像，“Image2”为以Y轴为对称轴翻转或水平镜像，“Images3”为以X轴和Y轴翻转。

# 二.图像仿射

图像仿射变换又称为图像仿射映射，是指在几何中，一个向量空间进行一次线性变换并接上一个平移，变换为另一个向量空间。通常图像的旋转加上拉升就是图像仿射变换，仿射变换需要一个M矩阵实现，但是由于仿射变换比较复杂，很难找到这个M矩阵，OpenCV提供了根据变换前后三个点的对应关系来自动求解M的函数：

• cv2.getAffineTransform(pos1,pos2)

其中pos1和pos2表示变换前后的对应位置关系，输出的结果为仿射矩阵M，接着使用函数cv2.warpAffine()实现图像仿射变换。图7-4是仿射变换的前后效果图。

图像仿射变换的函数原型如下：

• M = cv2.getAffineTransform(pos1,pos2)
– pos1表示变换前的位置
– pos2表示变换后的位置

• cv2.warpAffine(src, M, (cols, rows))
– src表示原始图像
– M表示仿射变换矩阵
– (rows,cols)表示变换后的图像大小，rows表示行数，cols表示列数

实现代码如下所示：

# -*- coding: utf-8 -*-
# By：Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取图片

#获取图像大小
rows, cols = src.shape[:2]

#设置图像仿射变换矩阵
pos1 = np.float32([[50,50], [200,50], [50,200]])
pos2 = np.float32([[10,100], [200,50], [100,250]])
M = cv2.getAffineTransform(pos1, pos2)

#图像仿射变换
result = cv2.warpAffine(src, M, (cols, rows))

#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()


输出结果如图7-5所示：

# 三.图像透视

图像透视变换（Perspective Transformation）的本质是将图像投影到一个新的视平面，同理OpenCV通过函数cv2.getPerspectiveTransform(pos1,pos2)构造矩阵M，其中pos1和pos2分别表示变换前后的4个点对应位置。得到M后在通过函数cv2.warpPerspective(src,M,(cols,rows))进行透视变换。

图像透视变换的函数原型如下：

• M = cv2.getPerspectiveTransform(pos1, pos2)
– pos1表示透视变换前的4个点对应位置
– pos2表示透视变换后的4个点对应位置

• cv2.warpPerspective(src,M,(cols,rows))
– src表示原始图像
– M表示透视变换矩阵
– (rows,cols)表示变换后的图像大小，rows表示行数，cols表示列数

假设现在存在一张A4纸图像，现在需要通过调用图像透视变换校正图像。

图像透视变换的校正代码如下所示，代码中pos1表示透视变换前A4纸的四个顶点，pos2表示透视变换后A4纸的四个顶点。

# -*- coding: utf-8 -*-
# By：Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取图片

#获取图像大小
rows, cols = src.shape[:2]

#设置图像透视变换矩阵
pos1 = np.float32([[114, 82], [287, 156], [8, 322], [216, 333]])
pos2 = np.float32([[0, 0], [188, 0], [0, 262], [188, 262]])
M = cv2.getPerspectiveTransform(pos1, pos2)

#图像透视变换
result = cv2.warpPerspective(src, M, (190, 272))

#显示图像
cv2.imshow("original", src)
cv2.imshow("result", result)

#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()


最终输出结果如图7-7所示，它将图形校正显示。

# 四.总结

本章主要讲解Python和OpenCV的图像几何变换，详细介绍了图像镜像、图像仿射和图像透视，包括歪曲图像纠正的案例，希望大家喜欢。此外，这些知识点也是我们PC端或手机端图像处理应用常见的算法，读者可以尝试结合这些应用完成一套图像处理软件。

最近寒假日更，为了感谢读者。同时感谢在求学路上的同行者，不负遇见，勿忘初心。图像处理系列主要包括三部分，分别是：

这周的留言感慨～

十二年CSDN的博客分享，如果要说分享最让我开心的是什么？不是传道，不是授业，也不是解惑，而是接下来这类事。这些年已经陆续鼓励了一些朋友当老师，而昨天得知这一位博友真的去到新疆南疆成为了一名小学老师，我很是感动，是真的感动，六年前我曾鼓励他如果想，就放弃高额工资的互联网大厂，去做自己想做的，没想到已经当了四年老师。又当爹又当妈，国语普及，文化教育，这里面的艰辛不是一两句道得清，除了佩服就是鼓励。
正如你说的一样，“一辈子总得做点有意义的事情，生命实在太短暂，一定要活得积极、正面”。或许，这也是我在CSDN分享博客的最大意义，再比如云南那位老友的留言，“农村的孩子下雨没有伞，只能拼命奔跑”，希望你以后也能成为一名教师，感恩有你们，感谢有你们。我也希望自己早日毕业回到家乡，花上三四十年做好两件事，一是认真教书，二是将少数民族文物抢救和文字语音保护做好，也鼓励更多人一起加入进来。自己虽然很菜吧，但还是有一些喜欢的事，尤其陪伴爱的人，挺好，爱你们喔。2022年继续加油，在CSDN分享更高质量的博客和专栏。

(By:娜璋之家 Eastmount 2022-01-27 夜于贵阳 https://blog.csdn.net/Eastmount )

参考文献：

• [1]冈萨雷斯. 数字图像处理（第3版）[M]. 北京：电子工业出版社, 2013.
• [2]阮秋琦. 数字图像处理学（第3版）[M]. 北京：电子工业出版社，2008.
• [3]毛星云, 冷雪飞. OpenCV3编程入门[M]. 北京：电子工业出版社, 2015.
• [4]Eastmount. [Python图像处理] 六.图像缩放、图像旋转、图像翻转与图像平移[EB/OL]. (2018-09-06). https://blog.csdn.net/Eastmount/article/details/82454335.
• [5]Eastmount. [数字图像处理] 六.MFC空间几何变换之图像平移、镜像、旋转、缩放详解[EB/OL]. (2015-06-04). https://blog.csdn.net/Eastmount/article/details/46345299.
展开全文
• 仿射变换 仿射变换是一种二维坐标到二维坐标之间的线性变换，它保持了二维图形的“平直性”（直线经过变换之后依然是直线）和“平行性”（二...opencv显示仿射变换前后的图像 import cv2 import numpy as np...
• Python中的图像处理（第五章）Python图像几何变换（3）前言一. Python准备二. Python仿真三. 小结 前言 随着人工智能研究的不断兴起，Python的应用也在不断上升，由于Python语言的简洁性、易读性以及可扩展性，特别...
• 使用python以及numpy通过直接操作图像数组完成一系列基本的图像处理 numpy简介： NumPy是一个非常有名的 Python 科学计算工具包,其中包含了大量有用的工具,比如数组对象(用来表示向量、矩阵、图像等)以及线性代数...
• opencv for python的4种图像几何变换 一、 图像变换简介 **1.变换简介：**首先图像是由一系列数组构成，对图像进行变换就是对数组进行操作，则需要一个变换数组来进行对原数组的操作从而完成对图像的操作，也就是说...
• Python中的图像处理（第五章）Python图像几何变换（2）前言一. Python准备二. Python仿真三. 小结 前言 随着人工智能研究的不断兴起，Python的应用也在不断上升，由于Python语言的简洁性、易读性以及可扩展性，特别...
• 欢迎大家来到“Python从零到壹”，在这里我将分享约200篇Python系列文章，带大家一起去学习...这篇文章将详细讲解图像几何变换，包括图像平移、图像缩放和图像旋转。希望文章对您有所帮助，如果有不足之处，还请海涵。
• 该系列文章是讲解Python ...前面的第六篇文章讲解了图像缩放、图像旋转、图像翻转和图像平移的几何变换，本篇文章主要讲解图像仿射变换和图像透视变换，通过Python调用OpenCV函数实。基础性知识希望对您有所帮助。
• 主要介绍了Python3+OpenCV2实现图像几何变换(平移、镜像、缩放、旋转、仿射),小编觉得挺不错的，现在分享给大家，也给大家做个参考。一起跟随小编过来看看吧
• 这篇文章中简单总结了图像几何变换中的平移变换、旋转变换、缩放变换、镜像变换以及仿射变换这五个部分，并介绍了它们的原理；其中参考的一些文章已经添加了链接，如果想进行更加全面的学习可以点进去进行查看。
• 详解Python+OpenCV进行基础的图像操作

...