pyhton:圖像旋轉


最近一個作業中要用到圖像旋轉,分享一下學習過程。如有講錯的地方,懇請指正!

圖像旋轉,想想真簡單啊,不就是將圖像矩陣乘上一個旋轉平移矩陣就完了嗎?實際上還真沒這么簡單。首先這個旋轉平移矩陣怎么獲得?通過這篇博客我們能夠輕松理解這個過程。http://www.cnblogs.com/xianglan/archive/2010/12/26/1917247.html

該旋轉平移矩陣可以通過以圖像左上角為原點的矩陣坐標系轉換到以圖像中心為原點的笛卡爾坐標系,再乘上一個旋轉矩陣,再將旋轉后的圖像轉換到原點矩陣坐標系。

當然,通過實驗我也獲得了該博客中所提到的蜂窩點。

當然要獲得完整的圖片,這篇博文也有程序。針對蜂窩點,我嘗試中值濾波,但使用cv2.medianBlur(iLRotate30, 3)對圖像濾波時,總是報錯

cv2.error: ..\..\..\opencv-2.4.13\modules\imgproc\src\smooth.cpp:1695: error: (-210)  in function cv::medianBlur

搞了半天,不知為啥,尷尬只好自己寫了一個中值濾波。順便把本文中的cv程序改成cv2方便對圖像數據的處理。

import cv2
import math
from numpy import *
import numpy as np

def rotate(image, angle):
    rows, cols, nchan = np.shape(image)
    anglePi = angle * math.pi / 180.0
    cosA = math.cos(anglePi)
    sinA = math.sin(anglePi)
    X1 = math.ceil(abs(0.5 * rows * cosA + 0.5 * cols * sinA))
    X2 = math.ceil(abs(0.5 * rows * cosA - 0.5 * cols * sinA))
    Y1 = math.ceil(abs(-0.5 * rows * sinA + 0.5 * cols * cosA))
    Y2 = math.ceil(abs(-0.5 * rows * sinA - 0.5 * cols * cosA))
    rows_new = int(2 * max(Y1, Y2))
    cols_new = int(2 * max(X1, X2))
    iLrotate = zeros((rows_new + 1, cols_new + 1, nchan), dtype=uint8)
    for i in xrange(rows):
        for j in xrange(cols):
            x = int(cosA * i - sinA * j - 0.5 * cols * cosA + 0.5 * rows * sinA + 0.5 * cols_new)
            y = int(sinA * i + cosA * j - 0.5 * cols * sinA - 0.5 * rows * cosA + 0.5 * rows_new)
            # if x > -1 and x < rows and y > -1 and y < cols:
            iLrotate[x, y] = image[i, j]
    return iLrotate
def rgb2gray(im):
    gray = im[:, :, 0]*0.2989+im[:, :, 1]*0.5870+im[:, :, 2]*0.1140
    return gray
def medianFilter(image,size):
    rows, cols, nchan = image.shape
    b = size / 2
    index_median = (size**2 - 1)/2
    for i in xrange(b, rows - b):
        for j in xrange(b, cols - b):
            for k in xrange(nchan):
                temp = image[i-b:i+b+1, j-b:j+b+1, k].ravel()
                temp = sorted(temp)
                image[i, j, k] = temp[index_median]
    return image
if __name__ == "__main__":
    image = cv2.imread('lena.jpg')
    iLRotate30 = rotate(image, 30)
    iLRotate90 = rotate(image, 90)
    cv2.imshow('image', image)
    iLRotate30_blur = cv2.medianBlur(iLRotate30, 3)
    iLRotate90_blur = medianFilter(iLRotate90, 3)
    cv2.imshow('iLRotate30', iLRotate30_blur)
    cv2.imshow('iLRotate90', iLRotate90_blur)
    cv2.waitKey(0)

雖然,沒有蜂窩點了,但是圖片信息有損失,而且很明顯。為啥用opencv或者PIL旋轉后的圖像沒有蜂窩點,且清洗度不減弱?

from PIL import Image
import matplotlib.pyplot as plt
pil_im = Image.open('lena.jpg')
plt.imshow(pil_im)
plt.show()
pil_im1 = pil_im.rotate(30)
plt.axis('off')
pil_im1.save('./ImageProcessed/rotated30_PIL.png')
plt.imshow(pil_im1)
plt.show()
pil_im2 = pil_im.rotate(90)
plt.axis('off')
pil_im2.save('./ImageProcessed/rotated90_PIL.png')
plt.imshow(pil_im2)
plt.show()

import cv2
import matplotlib.pyplot as plt
img = cv2.imread('lena.jpg')
# img = img / 255.0
rows, cols = img.shape[:2]
#第一個參數旋轉中心,第二個參數旋轉角度,第三個參數:縮放比例
M1 = cv2.getRotationMatrix2D((cols/2, rows/2), 30, 1)
M2 = cv2.getRotationMatrix2D((cols/2, rows/2), 90, 1)
#第三個參數:變換后的圖像大小
res1 = cv2.warpAffine(img, M1, (rows, cols))
res2 = cv2.warpAffine(img, M2, (rows, cols))
cv2.imwrite('./ImageProcessed/rotated30_cv2.png', res1)
cv2.imwrite('./ImageProcessed/rotated90_cv2.png', res2)
cv2.imshow('Ori', img)
cv2.imshow('Rotated1', res1)
cv2.imshow('Rotated2', res2)

這兩種旋轉方式相比之下,我更喜歡后者。因為,可以調整圖像旋轉中心位置,和縮放的比例。python下opencv圖像變換的詳細介紹可以看這兩篇博客。http://www.myexception.cn/image/1958561.html

http://www.tuicool.com/articles/rq6fIn

至於為啥這兩種方法效果比自己寫的好,可能是因為它們對旋轉后的圖像先差值后濾波。(僅是我的猜測而已,改天看看別人的源碼就清楚了)

 


免責聲明!

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



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