zoukankan      html  css  js  c++  java
  • 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

    至于为啥这两种方法效果比自己写的好,可能是因为它们对旋转后的图像先差值后滤波。(仅是我的猜测而已,改天看看别人的源码就清楚了)

  • 相关阅读:
    ORA01157、01110问题解决
    [转]WebService 中Maximum request length exceeded. 产生错误的原因,以及解决方法.
    [转]oracle9 startup时 报错ORA00600: 参数: [kcratr1_lostwrt]
    [转]八个dos命令
    [转]如何让ActiveX OCX控件下载并自动更新
    ora12154错误
    [转]Oracle分页
    [转]客户端连接数据库报错,ORA12516: TNS: 监听程序无法找到匹配协议栈的可用句柄
    vue中使用on事件被覆盖
    移动端滑动插件
  • 原文地址:https://www.cnblogs.com/subic/p/6618608.html
Copyright © 2011-2022 走看看