計算機視覺之幾何變換(實現圖片縮放、剪切、移位、鏡像、仿射變換、旋轉等功能)


1.圖片的縮放

圖片是由許多基本的像素點組成的,一般來說彩色圖像中的像素點由三個數值組成,分別是藍色分量、紅色分量和綠色分量。

圖片縮放分為:

  1. 普通的縮放,即確定下縮放后的尺寸大小,再進行縮放。
  2. 等比例縮放,即確定一個比例系數,長寬都乘以一個相同的比例系數,實現等比例縮放。

一般來說,圖片的縮放方法有:

  1. 最近臨域插值
  2. 雙線性插值(默認情況)
  3. 像素關系重采樣
  4. 立方插值

下面簡單實現等比例縮放,用最近領域插值方法實現,測試代碼如下:

 1 # encoding:utf-8
 2 # 基本實現步驟:
 3 # 1 load 讀取圖片
 4 # 2 info 獲取圖片信息
 5 # 3 resize 實現圖片縮放即改變圖片大小
 6 # 4 check 展示操作后的圖像
 7 import cv2
 8 img = cv2.imread('image0.jpg', 1)
 9 # 圖片的大小
10 imgInfo = img.shape
11 print(imgInfo)
12 height = imgInfo[0]
13 width = imgInfo[1]
14 mode = imgInfo[2]  # 為3 表示一個像素點由三個數值組成
15 cv2.imshow('src', img)
16 # 1 放大 縮小
17 # 2 等比例縮放 寬高比不變即為等比例縮放
18 # 等比例縮放 長寬乘以一個相同的系數
19 dstHeight = int(height*0.5)
20 dstWidth = int(width*0.5)
21 # 非等比例縮放
22 # dstHeight = 500
23 # dstWidth = 500
24 # 縮放方法:最近臨域插值 雙線性插值(默認情況) 像素關系重采樣 立方插值
25 dst = cv2.resize(img, (dstWidth, dstHeight))
26 cv2.imshow('image', dst)
27 cv2.waitKey(0)

運行效果如下:(src為原始圖像,dst為目標圖像即縮放后的圖像)

原始圖像:

 縮放后的圖像:

下面簡單的說下最近臨域插值的雙線性插值(默認情況)的原理:

 1 # 原圖像src 10*20 目標圖像dst 5*10
 2 # src-->dst
 3 # (2,4)-->(1,2)
 4 # 計算公式 dst x 1 -> src x 2 newX
 5 # newX=x*(src的行/dst的行) newX=1*(10/5)=2
 6 # newY=y*(src的列/目標的列) newY=2*(20/10)=4
 7 # 12.3 = 12 最近領域插值法 取最近的整數
 8 #
 9 # 雙線性插值法
10 # A1=20% 上+ 80% 下 A2
11 # B1=30% 左+ 70% 右 B2
12 # 1 最終點 = A1 30% + A2 70%
13 # 2 最終點 = B1 20% + B2 80%

簡單的實現下最近領域插值算法,測試代碼如下:

 1 # 最近臨域插值算法代碼實現
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 imgInfo = img.shape
 6 height = imgInfo[0]
 7 width = imgInfo[1]
 8 dstHeight = int(height/3)
 9 dstWidth = int(width/2)
10 dstImage = np.zeros((dstHeight, dstWidth, 3), np.uint8)  # 0-255 創建一個空白模版
11 for i in range(0, dstHeight):  #
12     for j in range(0, dstWidth):  #
13         iNew = int(i*(height*1.0/dstHeight))
14         jNew = int(j*(width*1.0/dstWidth))
15         dstImage[i, j] = img[iNew, jNew]
16 cv2.imshow('dst', dstImage)
17 cv2.waitKey(0)

運行結果如下:(即展示縮放后的圖像)

圖像的縮放再測試,代碼如下:

 1 # 圖片縮放
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 cv2.imshow('src', img)
 6 imgInfo = img.shape
 7 height = imgInfo[0]
 8 width = imgInfo[1]
 9 matScale = np.float32([[0.5, 0, 0], [0, 0.5, 0]])
10 dst = cv2.warpAffine(img,matScale,(int(width/2),int(height/2)))
11 cv2.imshow('dst',dst)
12 cv2.waitKey(0)

運行結果如下:(src為初始圖像,dst為目標圖像)

src初始圖像:

dst縮放后的圖像:

2.圖片的剪切

圖片剪切的大致原理,按照我的理解就是:確定兩個點,連接兩個的線段即為剪切矩陣的對角線,通過這兩個的坐標,就可以確定需要剪切的矩陣的方位以及矩陣大小。

更通俗一點的理解就是,你在用QQ截圖的時候,總是先點一個起始點,最后再點一個終止點,最后形成一個矩陣,最后再輸出這個矩陣中所有的像素值,即為剪切后的圖片。

圖片的剪切,測試代碼如下:

1 # 實現圖片的剪切
2 import cv2
3 img = cv2.imread('image0.jpg', 1)
4 cv2.imshow('src', img)
5 imgInfo = img.shape
6 # dst = img[100:500, 200:500]
7 dst = img[100:400, 100:500]  # 前面是縱向的范圍 后面的是橫向的范圍
8 cv2.imshow('image', dst)
9 cv2.waitKey(0)

運行結果如下:(src為原始圖像,image為目標圖像)

src原始圖像:

image剪切后的圖像:(剪了一朵大發發)

 3.圖片的移位

通過api調用實現圖片的移位,測試代碼如下:

 1 # 通過api調用實現圖片的移位
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 imgInfo = img.shape
 6 height = imgInfo[0]
 7 width = imgInfo[1]
 8 img = cv2.resize(img,(int(height*0.5),int(width*0.5)))  # 原始圖像長寬縮小一半
 9 cv2.imshow('src', img)
10 # 移位矩陣
11 matShift = np.float32([[1,0,50],[0,1,100]])  # 第一個移位矩陣
12 matShift2 = np.float32([[1,0,200],[0,1,100]])  # 第二個移位矩陣
13 # 目標矩陣
14 dst = cv2.warpAffine(img,matShift,(height,width-200))  # 第一個目標矩陣
15 dst2 = cv2.warpAffine(img,matShift2,(height,width-200))  # 第二個目標矩陣
16 # 展示兩個目標圖像
17 cv2.imshow('dst',dst)
18 cv2.imshow('dst2',dst2)
19 cv2.waitKey(0)

運行結果如下:(src為測試圖像,dst為第一個移位后的圖像,dst2為第二個移位后的圖像)

src測試圖像:

dst第一個移位圖像:

dst2第二個移位圖像:

自行實現圖片向右移動100個像素,測試代碼如下:

 1 # 自行實現圖片向右移動100個像素
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 img = cv2.resize(img,(int(img.shape[0]*0.5),int(img.shape[1]*0.5)))
 6 cv2.imshow('src',img)
 7 imgInfo = img.shape
 8 height = imgInfo[0]
 9 width = imgInfo[1]
10 dst = np.zeros(img.shape,np.uint8)
11 for i in range(0,height):
12     for j in range(0,width-100):
13         dst[i,j+100]=img[i,j]
14 cv2.imshow('image',dst)
15 cv2.waitKey(0)

運行結果如下:(src為原始圖像,image為移位后的圖像)

src原始圖像:

image移位后的圖像:

 4.圖片鏡像

圖像鏡像的實現步驟是:

  1. 先創建一個最夠大的畫板,能夠“裝得下”鏡像化之后的圖像
  2. 然后再將該圖像分別從前向后、從后向前繪制
  3. 最后繪制中心分割線

測試代碼如下:

 1 import cv2
 2 import numpy as np
 3 img = cv2.imread('image0.jpg', 1)
 4 img = cv2.resize(img,(int(img.shape[0]*0.5),int(img.shape[1]*0.3)))
 5 cv2.imshow('src', img)
 6 imgInfo = img.shape
 7 height = imgInfo[0]
 8 width = imgInfo[1]
 9 deep = imgInfo[2]
10 newImgInfo = (height*2, width, deep)
11 dst = np.zeros(newImgInfo, np.uint8)
12 for i in range(0, height):
13     for j in range(0, width):
14         dst[i, j] = img[i, j]
15         # x y = 2*j - y- 1
16         dst[height*2-i-1, j] = img[i, j]
17 for i in range(0, width):
18     dst[height, i] = (0, 0, 255)
19 cv2.imshow('image', dst)
20 cv2.waitKey(0)

運行結果如下:(src為初始圖像,image為鏡像后的圖像)

src初始圖像:

image鏡像后的圖像:

5.圖片的放射變換

放射變換融合了如下幾點:

  • 位移
  • 旋轉
  • 縮放

 測試代碼如下:

 1 # 仿射變換:位移 旋轉 縮放
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 cv2.imshow('src', img)
 6 imgInfo = img.shape
 7 height = imgInfo[0]
 8 width = imgInfo[1]
 9 # src 3->dst 3 (左上角 左下角 右上角)
10 matSrc = np.float32([[0,0],[0,height-1],[width-1,0]])
11 matDst = np.float32([[50,50],[300,height-200],[width-300,100]])
12 # 組合
13 matAffine = cv2.getAffineTransform(matSrc,matDst)
14 dst = cv2.warpAffine(img,matAffine,(width,height))
15 cv2.imshow('dst',dst)
16 cv2.waitKey(0)

運行結果如下:(src為初始圖像,dst為目標圖像)

src初始圖像:

dst目標圖像:

6.圖片的旋轉

 調用api實現圖片的旋轉,測試代碼如下:(主要有三個參數,旋轉中心的坐標、旋轉角度以及縮放系數(至於為什么有縮放系數,因為旋轉的時候可能會觸碰到圖像矩陣框的邊緣,所以需要縮放處理))

 1 # 圖片旋轉
 2 import cv2
 3 import numpy as np
 4 img = cv2.imread('image0.jpg', 1)
 5 img = cv2.resize(img,(int(img.shape[0]*0.5),int(img.shape[1]*0.5)))
 6 cv2.imshow('src', img)
 7 imgInfo = img.shape
 8 height = imgInfo[0]
 9 width = imgInfo[1]
10 # 得到旋轉矩陣 center angle sc 中心點 角度 縮放系數
11 matRotate = cv2.getRotationMatrix2D((height*0.5,width*0.5),45,0.7)
12 dst = cv2.warpAffine(img,matRotate,(height,int(width*1.5)))
13 cv2.imshow('image',dst)
14 cv2.waitKey(0)

運行效果如下:(src為初始圖像,image為目標圖像)

src初始圖像:

image目標圖像:

 暫時先記下這么多,還有的話再更新。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM