2017-11-18 00:59
'''原來寫的代碼太過凌亂,又花了5個小時重寫了代碼,把大部分功能定義成了函數,代碼總行數比原來少了10%。
幸好是python語言,如果用c語言,估計得寫三四百行,python的優點就是語法簡單,比其他語言更貼近人類的
語法,這些代碼中也使用了pythonic,使代碼可讀性提高了一點'''
import numpy as np#導入numpy庫,並命名爲np,之後會用到
def run():#定義函數run()
#這裏狗圖的儲存位置爲'e:\\images\\12.bmp',狗圖爲12.bmp,可自行更改
fp=open('e:\\img\\12.bmp','rb')
fheader=fp.read(54)#讀取12.bmp的前54字節,賦值給fheader。
fp.seek(18,0)#使讀指針定位到文件起始處向後偏移18字節
'''在24位bmp位圖中,第19~22這四個字節儲存了圖片的寬度,第23~26這四字節儲存了圖片的高度'''
#讀取圖片大小,oct1()可以將4字節的16進制數組轉化爲10進制
width=oct1(fp.read(4))
height=oct1(fp.read(4))
#定義一個元素全爲0的矩陣,用來儲存生成的圖像矩陣,元素類型爲16位整型
image=np.zeros((height,width),dtype=np.uint16)
fp.seek(54,0)
'''使讀指針定位到文件起始處向後偏移54字節,從這裏向後就是24位bmp圖像的數據區,
每3字節代表一個像素,這三個字節依次儲存藍、綠、紅三種顏色的亮度。'''
num=er(width)#確定每行像素後應該添加的字節數
'''根據bmp文件的格式,每一行像素對應的字節數應是4的倍數,不足要補0.例如一張24位的bmp位圖大小爲13*11,那麼這張圖片
的寬度就是13px(px表示像素),上面已經說過24位位圖每三字節表示一個像素,因此13*3=39,39字節表示了一行像素,但39不是4的
倍數,還差一個字節,於是就會在每行後面添加一個空字節(0x00)。'''
for i in range(height):
for j in range(width):
chs=fp.read(3)#chs是一個數組,可以儲存三個字節,python的一個好處就是你可以不用自己定義變量
f1=np.uint16(chs[0])
f2=np.uint16(chs[1])
f3=np.uint16(chs[2])
image[height-1-i][j]=f1+f2+f3
fp.seek(num,1)
'''把三個字節轉換爲整數後相加,確定像素的值,然後賦給數組image,位圖的儲存方式有點特別,例如,第55~57字節
所代表的那個像素,其實在圖片的左下角,整個文件最後的一個像素在圖片的右上角'''
fp.close()#關閉12.bmp文件
image_expand=expand(image)#將擴充後的矩陣賦給image_expand
image_gaus=gaus(image_expand,3,1)#使用定義的gaus()函數,把生成高斯濾波後的矩陣賦給image_gaus,image爲原圖像
fw(image_gaus,'e:\\13g.bmp',fheader)#生成濾波處理後的圖片,文件路徑爲'e:\\13g.bmp',fheader是54字節的文件頭
image_gaus_expand=expand(image_gaus)#擴充經過高斯濾波後的矩陣
image_gaus_sobel=sobel(image_gaus_expand)
fw(image_gaus_sobel,'e:\\13s.bmp',fheader)
#將16進制轉化爲10進制
def oct1(a):
num=a[0]+a[1]*16*16+a[2]*16*16*16+a[3]*16*16*16*16
return num
#計算在字節數不是4的倍數時應該補加的字節數
def er(width):
if (width*3)%4==3:
error=1
elif (width*3)%4==2:
error=2
elif (width*3)%4==1:
if (width*3+1)%4==2:
error=3
else:
error=1
else:
error=0
return error
#定義擴充函數,這個函數可以在矩陣四周添加0,image爲原數組,函數回返回生成的數組
def expand(image):
height=image.shape[0]
width=image.shape[1]
image_expand=np.zeros((height+2,width+2),dtype=np.uint16)
for i in range(height+2):
if i==0:
image_expand[0]=0
elif i>0 and i<(height+1):
image_expand[i][0],image_expand[i][width+1]=0,0
for b in range(width):
image_expand[i][b+1]=image[i-1][b]
else:
image_expand[i]=0
return image_expand
#參數依次爲原圖像,高斯濾波卷積核大小,sigma值
def gaus(image,size,sigma):
height=image.shape[0]-2
width=image.shape[1]-2
center=size/2
gaus_kernels=np.zeros((size,size))
sum=0
for i in range(size):
for j in range(size):
gaus_kernels[i][j]=(1/(2*np.pi*sigma*sigma))*np.exp(-((i-center)*(i-center)+(j-center)*(j-center))/(2*sigma*sigma))
sum=sum+gaus_kernels[i][j]
for m in range(size):
for n in range(size):
gaus_kernels[m][n]=gaus_kernels[m][n]/sum#高斯濾波卷積核
i,j=0,0 #令i,j的值等於零,方便下一次循環
gaus_cen=np.zeros((size,size))#作爲中間值,儲存截取出的3*3矩陣
gaus_image=np.zeros((height,width))#儲存轉換完成後的矩陣
for i in range(height):
for j in range(width):
gaus_cen[0][0]=image[i][j]
gaus_cen[0][1]=image[i][j+1]
gaus_cen[0][2]=image[i][j+2]
gaus_cen[1][0]=image[i+1][j]
gaus_cen[1][1]=image[i+1][j+1]
gaus_cen[1][2]=image[i+1][j+2]
gaus_cen[2][0]=image[i+2][j]
gaus_cen[2][1]=image[i+2][j+1]
gaus_cen[2][2]=image[i+2][j+2]
gaus_image[i][j]=np.sum(gaus_cen*gaus_kernels)
#兩個矩陣對應元素相乘,np.sum可以求矩陣中的所有元素相加的和
return gaus_image
def sobel(image):
width,height=image.shape[1]-2,image.shape[0]-2
sobel_cen=np.zeros((3,3))#定義中間值
sobel_image=np.zeros((height,width))#用來存放生成的矩陣
sobel_x=np.array([[-1,0,1],[-2,0,2],[-1,0,1]])#sobel算子x軸方向
sobel_y=np.array([[1,2,1],[0,0,0],[-1,-2,-1]])#sobel算子y軸方向
for x in range(height):
for y in range(width):
sobel_cen[0][0]=image[x][y]
sobel_cen[0][1]=image[x][y+1]
sobel_cen[0][2]=image[x][y+2]
sobel_cen[1][0]=image[x+1][y]
sobel_cen[1][1]=image[x+1][y+1]
sobel_cen[1][2]=image[x+1][y+2]
sobel_cen[2][0]=image[x+2][y]
sobel_cen[2][1]=image[x+2][y+1]
sobel_cen[2][2]=image[x+2][y+2]
Gx=np.sum(sobel_cen*sobel_x)#sobel的Gx分向量
Gy=np.sum(sobel_cen*sobel_y)#sobel的Gy分向量
sobel_image[x][y]=np.sqrt(Gx*Gx+Gy*Gy)
return sobel_image
#定義這個函數用來把圖像矩陣寫入文件,生成圖像,參數依次爲圖像矩陣,輸出的文件路徑.
def fw(image,src,head):
fg=open(src,'wb')#以二進制寫入方式打開文件
width,height=image.shape[1],image.shape[0]
fg.write(head)
num=er(width)
for i in range(height):
for j in range(width):
fg.write(np.uint8(image[height-1-i][j]/3))
fg.write(np.uint8(image[height-1-i][j]/3))
fg.write(np.uint8(image[height-1-i][j]/3))
j+=2
for n in range(num):
fg.write(np.int8(0))
fg.close()
if __name__ == '__main__':
run()
‘’‘————霧雨流雲’‘’