图像处理二:仿射变换和透视变换

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yql_617540298/article/details/84783350

一、仿射变换(Affine Transformation)

        放射变换(平面变换、二维坐标变换):是空间直角坐标系的变换,从一个二维坐标变换到另一个二维坐标,仿射变换是一个线性变换,保持了图像的“平行性”和“平直性”,即图像中原来的直线和平行线,变换后仍然保持原来的直线和平行线。

       仿射变换比较常用的特殊变换有平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和剪切(Shear);

        仿射变换性质:

(1)仿射变化只有6个自由度(对应变换中的6个系数),仿射变换后相互平行直线仍然是平行直线,三角形映射后仍是三角形;但却不能保证四边形以上的多变性映射为等边数的多边形;

(2)仿射变换的乘积和逆变换仍是仿射变换;

(3)仿射变换包含:平移、旋转、缩放等几何变换。

二、透视变换(Perspective Transformation)

       透视变换(空间变换、三维坐标变换):是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。

三、源码

图像若需保存代码为:

cv2.imwrite("F:/b.jpg",res)

第一个参数:路径下,指定文件名;

第二个参数:保存的图像。 

1. 平移

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('F:/a.jpg')
H = np.float32([[1,0,100],[0,1,100]])
rows,cols = img.shape[:2]
res = cv2.warpAffine(img,H,(rows,cols)) #需要图像、变换矩阵、变换后的大小
plt.subplot(121)
plt.imshow(img)
plt.subplot(122)
plt.imshow(res)

2. 放缩

      resize()函数可以进行图像的放大、缩小,但需要选择合适的插值方式。

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('F:/a.jpg')
res1 = cv2.resize(img,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC)
height,width = img.shape[:2]
res2 = cv2.resize(img,(2*width,2*height),interpolation=cv2.INTER_CUBIC)
plt.subplot(131)
plt.imshow(img)
plt.subplot(132)
plt.imshow(res1)
plt.subplot(133)
plt.imshow(res2)

 

3. 旋转

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('F:/a.jpg')
rows,cols = img.shape[:2]
#第一个参数旋转中心,第二个参数旋转角度,第三个参数:缩放比例
M = cv2.getRotationMatrix2D((cols/2,rows/2),45,1)
#第三个参数:变换后的图像大小
res = cv2.warpAffine(img,M,(rows,cols))

plt.subplot(121)
plt.imshow(img)
plt.subplot(122)
plt.imshow(res)

 

4. 仿射

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('F:/a.jpg')
rows,cols = img.shape[:2]
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
#第三个参数:变换后的图像大小
res = cv2.warpAffine(img,M,(rows,cols))
plt.subplot(121)
plt.imshow(img)
plt.subplot(122)

5. 投影

(1)垂直投影

import cv2  
import numpy as np  
from matplotlib import pyplot as plt
  
img=cv2.imread('F:/a.jpg')
GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)   #将BGR图转为灰度图
ret,thresh1=cv2.threshold(GrayImage,130,255,cv2.THRESH_BINARY)  #将图片进行二值化(130,255)之间的点均变为255(背景)
(h,w)=thresh1.shape #返回高和宽
a = [0 for z in range(0, w)]  
#记录每一列的波峰
for j in range(0,w): #遍历一列 
    for i in range(0,h):  #遍历一行
        if  thresh1[i,j]==0:  #如果改点为黑点
            a[j]+=1  		#该列的计数器加一计数
            thresh1[i,j]=255  #记录完后将其变为白色          
for j  in range(0,w):  #遍历每一列
    for i in range((h-a[j]),h):  #从该列应该变黑的最顶部的点开始向最底部涂黑
        thresh1[i,j]=0   #涂黑
plt.imshow(thresh1,cmap=plt.gray())
plt.show()
cv2.imshow('img',thresh1)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

(2)水平投影

import cv2  
import numpy as np  
from matplotlib import pyplot as plt
  
img=cv2.imread('F:/a.jpg') 
GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
ret,thresh1=cv2.threshold(GrayImage,130,255,cv2.THRESH_BINARY)
 
(h,w)=thresh1.shape #返回高和宽
 
a = [0 for z in range(0, h)] 
 
for j in range(0,h):  
    for i in range(0,w):  
        if  thresh1[j,i]==0: 
            a[j]+=1 
            thresh1[j,i]=255
         
for j  in range(0,h):  
    for i in range(0,a[j]):   
        thresh1[j,i]=0    
 
plt.imshow(thresh1,cmap=plt.gray())

(3)基于投影的字符分割

import cv2
import numpy as np

path = 'F:/b.jpg'
root = 'F:/b/'
dsize = 28
img = cv2.imread(path)
data = np.array(img)
len_x = data.shape[0] 
len_y = data.shape[1]
min_val = 10 #设置最小的文字像素高度

start_i = -1
end_i = -1
rowPairs = [] #存放每行的起止坐标

#行分割
for i in range(len_x):
    if(not data[i].all() and start_i < 0): 
        start_i = i
    elif(not data[i].all()):
        end_i = i
    elif (data[i].all() and start_i >= 0):
        #print(end_i - start_i)
        if(end_i - start_i >= min_val):
            rowPairs.append((start_i, end_i))
        start_i, end_i = -1, -1
#列分割
start_j = -1
end_j = -1
min_val_word = 8  #最小文字像素长度
number = 0 #分割后保存编号
for start, end in rowPairs:
    for j in range(len_y):
        if(not data[start: end, j].all() and start_j < 0):
            start_j = j
        elif(not data[start: end, j].all()):
             end_j = j
        elif(data[start: end, j].all() and start_j >= 0):
            if(end_j - start_j >= min_val_word):
                #print(end_j - start_j)
                tmp = data[start:end, start_j: end_j]
                im2save = cv2.resize(tmp, (dsize,dsize)) #归一化处理
                cv2.imwrite(root + '%d.png' % number, im2save) 
                number += 1
                #print("%d  pic" % number)
            start_j, end_j = -1, -1

猜你喜欢

转载自blog.csdn.net/yql_617540298/article/details/84783350
今日推荐