python圖像旋轉
⑴ OpenCV python實現旋轉矩形的裁剪
環境
矩形操作是我們在 OpenCV 里最常用的操作,其中最為常見的就是包圍框( Bounding Box )和旋轉矩形( Rotated Box )。 其中包圍框是最為常見的,對應 OpenCV 中的 boundingRect() ,使用正矩形框處物體,一般多用在目標檢測中。使用包圍框框柱目標物體,這種操作比較簡單,但是通常框中也會有一些其他的區域。其次就是使用旋轉矩形,也叫最小外接矩形,對應 OpenCV 中的 minAreaRect() ,用來使用旋轉矩形最大限度的框出目標物體,減小背景干擾,在 OCR 任務中較為常用。
minAreaRect() 返回了所需區域的最小斜矩形的參數,與包圍框直接返回四個頂點的坐標不同,最小外接矩形返回的是矩形的 ((x, y), (w, h), angle) ,對應了矩形的中心,寬度,高度和旋轉角度。
旋轉角度 angle 是水平軸( x 軸)逆時針旋轉,與碰到的矩形的第一條邊的夾角。並且這個邊的邊長是 width ,另一條邊邊長是 height 。也就是說,在這里 width 與 height 不是按照長短來定義的。
在 OpenCV 中,坐標系原點在左上角,相對於 x 軸,逆時針旋轉角度為負,順時針旋轉角度為正,所以函數 minAreaRect() 返回的角度范圍時 [-90~0) 。想像一個平放的長矩形,調用 minAreaRect() 返回的角度為 -90 度。如果我們旋轉圖像,直到矩形樹立起來,這是調用 minAreaRect() 得到的角度依然是 -90 度。
第一種裁剪旋轉矩形的方法是通過仿射變換旋轉圖像的方式。
仿射變換( Affine Transformation ) 是一種二維坐標到二維坐標之間的線性變換,保持二維圖形的「平直性」( straightness ,即變換後直線還是直線不會打彎,圓弧還是圓弧)和「平行性」( parallelness ,其實是指保二維圖形間的相對位置關系不變,平行線還是平行線,相交直線的交角不變。)。
計算過程:
如果不做邊長和角度的判斷,則只會沿著 x 軸的順時針方向做相同大小角度的旋轉,不能保證旋轉後的視角是正確的視角:
根據任務目標的類型,做邊長和角度的判斷並進行相應的調整,可以保證旋轉後的視角是正確的視角:
第二種裁剪旋轉矩形的方法是通過透視變換直接將旋轉矩形的四個頂點映射到正矩形的四個頂點。
透視變換( Perspective Transformation )是將圖片投影到一個新的視平面( Viewing Plane ),也稱作投影映射( Projective Mapping )。
計算過程:
以上兩種方法都可以用來摳取旋轉矩形的內容。仿射變換方法需要預先對整張圖進行旋轉,通過觀察旋轉後的圖像可以發現,有一部分圖像被旋轉出了圖像邊界,如果你要摳取的目標正好在圖像邊緣附近,那麼很容易出界導致圖像摳取的缺失。同時我們需要對寬、高和角度做出動態的調整;透視變換的方法直接對摳取區域進行了映射,這種方法可以省略旋轉的步驟,並且不會出現摳取內容的缺失。同時我們只需要對4個頂點之間的映射關系做好定義即可,不需要考慮角度的問題。相對的,透視變換相對於仿射變換計算量更大一些,不過這在 c++ 的底層實現上帶來的時延差距小於 ms 。
⑵ 1.圖像裁剪、加邊框、旋轉(Python PIL)
日常工作中經常要用Photoshop列印一些地質圖,雖然說PS有動作錄制的功能,但是列印這個功能我嘗試過錄制動作後並未能成功運行,而且要列印的圖像尺寸很多都是不同的,試了幾次後就放棄了,直到後來Python學起來了,通過pywinauto庫實現了這個功能,在這里就簡單記錄下吧。
在寫Photoshop的列印操作之前,先來回顧下列印之前的圖像處理工作。
接到的地質圖多為MapGIS程序導出的jpg圖片,偶爾也會有Tif格式的遙感圖。對這些圖像進行列印很簡單,基本流程是:用PS打開圖像->裁剪圖像四周空白邊緣->為圖像四周加上3cm寬白色邊框(為了美觀和裝訂的需要)->列印。那為啥用PS來列印不直接用Windows自帶列印呢,應該是列印需要用到PS特定的顏色處理模式吧,經過試驗,通過兩種方式打出來的色彩效果確實是不同的。
列印前圖像處理的主要目標很簡單:
1、裁剪圖像四周空白
2、為圖像四周加上3cm白色邊框
下面就用Python實現它們
圖像處理主要用的是PIL這個庫,中途由於單位電腦比較舊(4g內存Win7 32位系統,後來重裝成64位了,體驗就是搞這種東西必須整個64位系統),性能不太行了,也用Opencv整了下,還是感覺PIL稍微快那麼一點點,不知道是不是錯覺呢。
(後來發現這兩步在PS錄個動作也能輕松完成(→ܫ←))
一、獲取所有圖片路徑
有時候要列印的圖片會放在好多個不同文件夾裡面,要把它們遍歷出來:
import os
二、讀取圖片並裁剪四周空白
import PIL
獲得了圖像尺寸後接下來就要對圖像進行邊緣空白的裁剪了(其實這兩步不分先後順序的):
裁剪的思路是網上搜到的,整理下就是:
1、先把圖像轉成灰度模式(值變成單一的0-255以方便判斷,如果要裁剪其他顏色我就不知道了,我這里只要裁掉最常見的由MapGIS導出的標準的白色邊緣)。
2、分別從四個方向掃描圖像,找到四個方向各自第一個灰度值不為255(最純粹的白色(→ܫ←))的像素,記下它的坐標(i,j)。
3、通過四組坐標大小比較,得到圖像除了四周空白區域外的坐標極值,也就得到了裁剪的區域左上(left,top)和右下坐標(right,bottom)。
4、利用PIL.Image.crop(),完成圖像的裁剪。
5、沒了,就是後來發現PIL自帶這個演算法,引用一下: 使用PIL裁剪圖片白邊
要是用PS來做呢,『圖像-裁切-確定』就完事了。
三、給裁剪後的圖像加上x厘米的白色邊框
這一步主要是為了列印出來的圖規范且美觀。
這一步要是用PS來搞,『圖像-畫布大小-設置相對的寬度和高度』 就好了
四、判斷圖像是否需要旋轉。
為什麼要旋轉這些圖像呢?因為最終是要把它們用列印機列印出來,而列印機能列印的最大寬度是有限的,所以就有了這個步驟。
單位的列印機型號是惠普的HP DesignJet Z6200 60 英寸照片列印機,最大列印紙張寬度是60英寸,大約就是1524mm左右吧,除了最大尺寸外,日常還用到的紙張寬度有440、610、914、1067、1274等6、7種吧,所以出於節約列印時間和省錢的考慮,為每張圖選擇最合適的列印紙張寬度也是很有必要的。
判斷圖像是否需要旋轉的思路是這樣的:
1、比較圖像的寬和高,判斷誰是圖像的長邊和短邊。
2、短邊如果大於1524mm,這圖按1:1就打不出來了,超過列印機最大可裝入的紙張的寬度,把這個圖像文件放到Oversize_path路徑下,後續自己看著辦。
3、在短邊小於等於1524mm的前提下,根據對圖像寬高和長短邊的比較,有兩種需要旋轉的情況:
3.1 如果圖像的寬是長邊(矮胖的矩形),且寬大於1524mm,那麼這圖得旋轉90°;
3.2 如果圖像的高是長邊(瘦高的矩形),且高小於1524mm,那麼這圖也得旋轉90°。
*printTOtkinter()是個用tkinter搞的進度顯示窗口,就輸出下一些文本信息而已。
五、為圖像選擇最合適的列印紙張尺寸
單位列印紙有438、610、914、1524等7種寬度,現在要選出最適合的一種來進行列印。
在把短邊大於1524這種情況排除之後,剩下的圖像情況為短邊小於1524,即單位的列印機能列印出來了。
這時要判斷最佳列印用紙的寬度,有兩種情況需要考慮:
1、長邊>1524,改用短邊來比較選擇列印紙寬度。
2、長邊 ≤ 1524,用長邊來比較選擇列印紙寬度。
下面思路就是把要用作比較的邊長放入紙張寬度列表,把列表排序後找到比這個邊長大一點的那個紙張寬度。
主要的步驟就是這些,再經過一頓復制粘貼完善一下其他細節之後,最後會得到一個存放列印信息的列表,把它用txt存起來,這樣後面的PS批量列印需要的信息就全部搞到手了。最後放個gif。
⑶ python做三維圖結果怎麼用滑鼠拖動旋轉
旋轉視角,要根據三角函數計算的,每轉動一個角度都需要重新計算,這些都需要實現,之後根據轉動的數值傳入進去,計算後,重新畫圖
⑷ 怎麼樣在python中讓最後畫出來的圖翻轉90度
importImage
importos
importglob
dir="f:mobile"
#取出指定文件
file=glob.glob(os.path.join(dir,'xxx.JPG'))
#打開圖片
img=Image.open(file)
#顯示圖片
img.show()
printimg.format,img.size,img.mode
print"rotatingimage....."
im=img.rotate(90)
im.save(image)
我不知道你怎麼畫的,但旋轉請參考以上代碼
⑸ python 圖片移動
#-*-coding:gbk-*-
importImage
importImageDraw
importImageChops
im=Image.new('RGB',(800,600),'white')
im2=Image.open('test.png')
#測試圖放畫布左邊,畫布右邊底色塗黃
left=(im.size[0]/2-im2.size[0])/2
upper=(im.size[1]-im2.size[1])/2
im.paste(im2,(left,upper))
im.paste('yellow',(im.size[0]/2,0)+im.size)
im.show()
#因要旋轉得計算測試圖對角線,然後切出
d=int((im2.size[0]**2+im2.size[1]**2)**0.5)
left=(im.size[0]/2-d)/2
upper=(im.size[1]-d)/2
bbox=(left,upper,left+d,upper+d)
cp=im.crop(bbox)
#圖底不是黑先做mask再作旋轉,
#mask做法不一,按測試圖可選取g或b通道
r,g,b=cp.split()
mask=g.point(lambdai:i<250and255)
angle=30
mask=mask.rotate(angle)
cp=cp.rotate(angle)
#利用mask貼在畫布右邊黃底區內
im.paste(cp,(left+im.size[0]/2,upper),mask)
im.show()
⑹ python可以用來處理圖像嗎
可以的,
PythonWare公司提供了免費的Python圖像處理工具包PIL(Python Image Library),該軟體包提供了基本的圖像處理功能,如:
改變圖像大小,旋轉圖像,圖像格式轉換,色場空間轉換,圖像增強,直方圖處理,插值和濾波等等。雖然在這個軟體包上要實現類似MATLAB中的復雜的圖像處理演算法並不太適合,但是Python的快速開發能力以及面向對象等等諸多特點使得它非常適合用來進行原型開發。
在PIL中,任何一副圖像都是用一個Image對象表示,而這個類由和它同名的模塊導出,因此,最簡單的形式是這樣的:
import Image img = Image.open(「dip.jpg」)
注意:第一行的Image是模塊名;第二行的img是一個Image對象;
Image類是在Image模塊中定義的。關於Image模塊和Image類,切記不要混淆了。現在,我們就可以對img進行各種操作了,所有對img的
操作最終都會反映到到dip.img圖像上。
PIL提供了豐富的功能模塊:Image,ImageDraw,ImageEnhance,ImageFile等等。最常用到的模塊是
Image,ImageDraw,ImageEnhance這三個模塊。下面我對此分別做一介紹。關於其它模塊的使用請參見說明文檔.有關PIL軟體包和
相關的說明文檔可在PythonWare的站點www.Pythonware.com上獲得。
Image模塊:
Image模塊是PIL最基本的模塊,其中導出了Image類,一個Image類實例對象就對應了一副圖像。同時,Image模塊還提供了很多有用的函數。
(1)打開一文件:
import Image img = Image.open(「dip.jpg」)
這將返回一個Image類實例對象,後面的所有的操作都是在img上完成的。
(2)調整文件大小:
import Image img = Image.open("img.jpg") new_img = img.resize
((128,128),Image.BILINEAR) new_img.save("new_img.jpg")
原來的圖像大小是256x256,現在,保存的new_img.jpg的大小是128x128。
就是這么簡單,需要說明的是Image.BILINEAR指定採用雙線性法對像素點插值。
在批處理或者簡單的Python圖像處理任務中,採用Python和PIL(Python Image Library)的組合來完成圖像處理任務是一個很不錯的選擇。設想有一個需要對某個文件夾下的所有圖像將對比度提高2倍的任務。用Python來做將是十分簡單的。當然,我也不得不承認Python在圖像處理方面的功能還比較弱,顯然還不適合用來進行濾波、特徵提取等等一些更為復雜的應用。我個人的觀點是,當你要實現這些「高級」的演算法的時候,好吧,把它交給MATLAB去完成。但是,如果你面對的只是一個通常的不要求很復雜演算法的圖像處理任務,那麼,Python圖像處理應該才是你的最佳搭檔。
⑺ python 圖像旋轉怎麼去除黑邊
去除黑邊現象的辦法:
1)在做圖像坐標映射反查的時候,算出當前點在原始圖像的外部還是內部,若在外部,判斷當前像素點的X或者Y位置,找臨近四個邊界的像
素值代替;
該方法太過繁瑣,適合自己寫程序實現,如若想調用現有的一些庫函數,可以考慮2)做法:
2)將待旋轉的圖像進行邊界填充,最不濟的情況下可以擴充為原始圖像的大小;
旋轉邊界填充圖像;
計算原始圖像經過旋轉以後的結果圖像的尺寸大小;
在邊界填充旋轉圖像上截取目標圖像;(圖像都是按照圖像中心旋轉的);
附上一段matlab人臉根據人眼位置對齊的代碼:
[plain] view plain
eye_angle = atan2( (eye_pts(2,2) - eye_pts(1,2)),(eye_pts(2,1) - eye_pts(1,1) ) ) * 180 / pi; % 人眼的傾斜角度
if eye_angle < 0
eye_angle = eye_angle + 360;
end
if floor(eye_angle) <= 5 || floor( 360 - eye_angle ) <= 5
continue;
end % 5度之內不做對齊操作
img = imread(img_path);
[m,n,~] = size(img);
img_pad = padarray(img,[m n],'both','replicate');% 擴充圖像
img_pad_rotate = imrotate(img_pad,eye_angle,'bilinear'); % 旋轉擴充圖像
[m_pad_r,n_pad_r,~] = size(img_pad_rotate);
[plain] view plain
eye_angle = eye_angle * pi / 180;
f_cos = cos(eye_angle);f_sin = sin(eye_angle);
new_m = floor(m * abs(f_cos) + n * abs(f_sin));
new_n = floor(n * abs(f_sin) + m * abs(f_cos));% 最終對齊圖像的大小
left = floor((n_pad_r - new_n) / 2);right = left + new_n;
bott = floor((m_pad_r - new_m) / 2);up = bott + new_m;
face_rorate = img_pad_rotate(bott : up,left : right,:); % 截取目標圖像
figure,imshow(face_rorate)
⑻ python opencv 批量旋轉圖像,使 圖像內容不改變,並保存
from PIL import Image
import os
import cv2
from math import *
import numpy as np
path_old ='G:'
degrees=[]
for k in range(1,25):
degrees.append(k*15)
for item in os.listdir(path_old):
in_imgpath = path_old + item
out_name = os.path.splitext(item)[0]
print(in_imgpath)