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()
‘’‘————雾雨流云’‘’