python圖像處理基礎(一)
寫在前面的話: 友善以後查文檔,且這篇文章會随着學習一直更(因為還有opencv還沒怎麼學,目前是一些基本的操作)。都是跟着學習資料鞏固的,隻供學習使用。
第一部分—— 圖像基本操作
縮略圖、截圖、部分變換、旋轉、圖像轉換為數組進行操作
- 讀取圖檔及灰階圖
from PIL import Image #導入PIL庫的Image類
import matplotlib.pyplot as plt
pil_im = Image.open('G:/photo/innovation/1.jpg') #讀取圖像檔案
pil_im_gray = pil_im.convert('L')
plt.subplot(121)
plt.imshow(pil_im)
plt.subplot(122)
plt.imshow(pil_im_gray)

縮略圖
thumbnail 或 resize
pil_im.thumbnail((128,128))
out= pil_im.resize((128,128))
截圖
(box is the crop rectangle, as a (left, upper, right, lower) tuple.)
box=(100,100,400,400)
region = pil_im.crop(box)
部分變換
transpose 之後 paste
region = region.transpose(Image.ROTATE_180)
pil_im.paste(region,box)
旋轉
rotate() 傳度數即可
圖像轉換為數組進行操作
可以對數組進行任意的灰階變換後再轉換為圖像輸出
im = np.array(Image.open('G:/photo/innovation/1.jpg'))
print(im.shape, im.dtype)
pil_im = Image.fromarray(im)
第二部分—— 圖像基本處理
灰階直方圖、直方圖均衡、空間濾波、圖像基本變換、仿射變換
灰階直方圖
contour作用是繪制等高線, hist 注意 im.flatten()
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
# read image to array
im = np.array(Image.open('G:/photo/innovation/1.jpg').convert('L'))
# create a new figure
plt.figure()
# don’t use colors
plt.gray()
# show contours with origin upper left corner
plt.contour(im, origin='image')
plt.axis('equal')
plt.axis('off')
plt.figure()
plt.hist(im.flatten(),128)
plt.show()
直方圖均衡
c ( I ) = 1 N ∗ ∑ I = 0 I h ( i ) = c ( I − 1 ) + 1 N ∗ h ( I ) c(I) = \frac{1}{N} * \sum_{I=0}^{I}{h(i)} = c(I - 1) + \frac{1}{N} *h(I) c(I)=N1∗I=0∑Ih(i)=c(I−1)+N1∗h(I)
我們要對圖像求直方圖,就需要先把圖像矩陣進行flatten操作,使之變為一維數組,然後再進行統計用reshape進行變換,實際上變換後還是二維數組,兩個方括号,是以隻能用 flatten.
- cumsum(): 計算累計和
- flatten(): 個人了解為合并清單
- interp(): 線性插值函數
- numpy.interp(x, xp, fp, left=None, right=None, period=None)
def histeq(im,nbr_bins=256):
""" Histogram equalization of a grayscale image. """
# get image histogram
imhist,bins = histogram(im.flatten(),nbr_bins,normed=True)
# 計算所有像素值
cdf = imhist.cumsum() # cumulative distribution function
# 得出第一個乘數
cdf = 255 * cdf / cdf[-1] # normalize
# use linear interpolation of cdf to find new pixel values
im2 = np.interp(im.flatten(),bins[:-1],cdf)
return im2.reshape(im.shape), cdf
from PIL import Image
import numpy as np
im = array(Image.open('G:/photo/innovation/1.jpg').convert('L'))
im2,cdf = histeq(im)
plt.figure(figsize=(18,10))
plt.subplot(231)
plt.hist(im.flatten(),256)
plt.subplot(232)
plt.plot(range(256),cdf)
plt.subplot(233)
plt.hist(im2.flatten(),256)
plt.subplot(234)
plt.gray()
plt.imshow(im)
plt.subplot(236)
plt.imshow(im2)
plt.show()
空間濾波
- 高斯濾波 gaussian_filter
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters
im = np.array(Image.open('G:/photo/innovation/1.jpg').convert('L'))
im2 = filters.gaussian_filter(im,5)
pil_im2 = Image.fromarray(uint8(im2))
plt.imshow(pil_im2)
圖像幾何變換
SciPy庫中的ndimage包的相關函數實作幾何變換,ndimage.affine_transform
im = np.array(Image.open('G:/photo/innovation/1.jpg').convert('L'))
H = np.array([[1.4,0.05,-100],[0.05,1.5,-100],[0,0,1]])
im2 = ndimage.affine_transform(im,H[:2,:2],(H[0,2],H[1,2]))
plt.figure()
plt.gray()
plt.imshow(im2)
plt.show()
仿射變換
- 圖像的坐标變換通常為仿射變換,其保留了共線性與距離比例
- 共線性:變換前在同一直線上的點變換後還在同一直線上。
- 距離比例:變換前後直線上各點之間的距離的比例保持不變。
- 仿射變換的一般形式
u = c 11 x + c 12 y + c 13 u = c_{11}x + c_{12}y + c_{13} u=c11x+c12y+c13 v = c 21 x + c 22 y + c 23 v = c_{21}x + c_{22}y + c_{23} v=c21x+c22y+c23
- c 13 , c 23 c_{13}, c_{23} c13,c23控制平移
- c 11 , c 12 , c 21 , c 22 c_{11}, c_{12}, c_{21}, c_{22} c11,c12,c21,c22控制縮放、旋轉和剪切
接下來将一張圖進行仿射變換後貼到另一張圖的指定位置
def Haffine_from_points(fp,tp):
""" Find H, affine transformation, such that tp is affine transf of fp. """
if fp.shape != tp.shape:
raise RuntimeError('number of points do not match')
'''
當 np.diag(array) 中,
array是一個1維數組時,結果形成一個以一維數組為對角線元素的矩陣
array是一個二維矩陣時,結果輸出矩陣的對角線元素
'''
# condition points
# --from points--
m = np.mean(fp[:2], axis=1)
maxstd = np.max(std(fp[:2], axis=1)) + 1e-9
C1 = np.diag([1/maxstd, 1/maxstd, 1])
C1[0][2] = -m[0]/maxstd
C1[1][2] = -m[1]/maxstd
fp_cond = np.dot(C1,fp)
# --to points--
m = np.mean(tp[:2], axis=1)
C2 = C1.copy() #must use same scaling for both point sets
C2[0][2] = -m[0]/maxstd
C2[1][2] = -m[1]/maxstd
tp_cond = np.dot(C2,tp)
# conditioned points have mean zero, so translation is zero
A = np.concatenate((fp_cond[:2],tp_cond[:2]), axis=0)
U,S,V = np.linalg.svd(A.T)
# create B and C matrices as Hartley-Zisserman (2:nd ed) p 130.
tmp = V[:2].T
B = tmp[:2]
C = tmp[2:4]
'''
vstack():堆棧數組垂直順序(行)
hstack():堆棧數組水準順序(列)
concatenate():連接配接沿現有軸的數組序列
'''
tmp2 = np.concatenate((dot(C,linalg.pinv(B)),zeros((2,1))), axis=1)
H = np.vstack((tmp2,[0,0,1]))
# decondition
H = dot(np.linalg.inv(C2),np.dot(H,C1))
return H / H[2,2]
def image_in_image(im1,im2,tp):
""" Put im1 in im2 with an affine transformation
such that corners are as close to tp as possible.
tp are homogeneous and counter-clockwise from top left. """
# points to warp from
m,n = im1.shape[:2]
fp = np.array([[0,m,m,0],[0,0,n,n],[1,1,1,1]])
# compute affine transform and apply
H = Haffine_from_points(tp,fp)
im1_t = ndimage.affine_transform(im1,H[:2,:2], (H[0,2],H[1,2]),im2.shape[:2])
alpha = (im1_t > 0)
return (1-alpha)*im2 + alpha*im1_t
# example of affine warp of im1 onto im2
im1 = np.array(Image.open('G:/photo/innovation/1.jpg').convert('L'))
im2 = np.array(Image.open('G:/photo/innovation/3.jpg').convert('L'))
tp = array([[158,310,304,141],[76,98,253,218],[1,1,1,1]])
im3 = image_in_image(im1,im2,tp)
plt.figure()
plt.gray()
plt.imshow(im3)
plt.axis('equal')
plt.axis('off')
plt.show()