# -*- coding: utf-8 -*-
“””
Spyder 编辑器
这是一个临时脚本文件。
“””
import tkinter as tk
import numpy as np
from PIL import Image,ImageTk
import tkinter.filedialog as tkfd
import tkinter.simpledialog as askdiag
import const
class window(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.resizable(0, 0)
self.title(‘main window’)
self.geometry(‘640×480’)
menuBar=tk.Menu(self) #创建一个菜单实例,
self[‘menu’]=menuBar #将菜单置于运行窗口中,一个窗口只能有一个菜单,并默认置于顶端
menu01=tk.Menu(menuBar,tearoff=False) #创建一个二级菜单,置于menuBar中
menuBar.add_cascade(label=’文件’,menu=menu01) #在menu0中添加一个label=’文件’ 为项目的级联菜单
menu01.add_command(label=’打开’,command=self.openfile) #添加二级菜单项
menu01.add_separator()#分割线
menu01.add_command(label=’保存’,command=self.savefile) #添加二级菜单项
menu01.add_separator()#分割线
menu01.add_command(label=’退出’,command=self.exitsys) #添加二级菜单项
menu02=tk.Menu(menuBar,tearoff=False) #创建一个二级菜单,置于menuBar中
menuBar.add_cascade(label=’图像操作’,menu=menu02) #在menuBar中添加一个label=’文件’ 为项目的级联菜单
menu02.add_command(label=’灰度化处理’,command=self.gray) #添加二级菜单项
menu02.add_separator()#分割线
menu02.add_command(label=’显示直方图’,command=self.hist) #添加二级菜单项
menu02.add_separator()#分割线
menu02.add_command(label=’阈值二值化’,command=self.binProc) #添加二级菜单项
menu02.add_separator()#分割线
menu02.add_command(label=’阈值区间二值化’,command=self.binProc2) #添加二级菜单项
menu03=tk.Menu(menuBar,tearoff=False) #创建一个二级菜单,置于menuBar中
menu03.add_command(label=’直方图均衡化’,command=self.histogram_match)
menu03.add_separator()#分割线
menuBar.add_cascade(label=’亮度操作’,menu=menu03) #在menu01中添加一个label=’文件’ 为项目的级联菜单
menu03.add_command(label=’对比度调节’,command=self.contrast_bright)
menu03.add_separator()#分割线
menu03.add_command(label=’对比度调节’,command=self.contrast_bright)
menu04=tk.Menu(menuBar,tearoff=False) #创建一个二级菜单,置于menuBar中
menuBar.add_cascade(label=’边缘检测’,menu=menu04) #在menu01中添加一个label=’文件’ 为项目的级联菜单
menu04.add_command(label=’robert算子’,command=self.robert)
menu04.add_separator()#分割线
menu04.add_command(label=’sobel算子’,command=self.sobel)
menu04.add_separator()#分割线
menu04.add_command(label=’Laplace算子’,command=self.laplace)
tp=tk.Frame(self)
tp.pack()
self.w=None
self.h=None
self.resizeimg=None #固定640*480大小图像,在窗口显示
self.imgarray=None # 加载图像的数组形式
self.photo=None #加载的图像
#self.canvasimg=None #使用PhotoImage转换为画布显示图像,用于画布显示
#使用Canvas显示图像
self.canvas=tk.Canvas(tp, width=640,height=480)
self.canvas.pack(fill = ‘both’,expand =’yes’)
self.canvas_on_image=self.canvas.create_image(0, 0, anchor=’nw’, image=None)
# robert 算子[[-1,-1],[1,1]]
def robert(self):
r_suanzi = [[-1,-1],[1,1]]
# for x in range(self.h-1):
# for y in range(self.w-1):
# self.imgarray[x, y,1] = abs(np.sum(r_suanzi*self.imgarray[x:x+2, y:y+2,1])) # 求和加绝对值
g=self.imgarray[:,:,1]
for i in range(g.shape[0]-1):
for j in range(g.shape[1]-1):
g[i,j]=abs(int(g[i+1,j])-int(g[i,j]))+abs(int(g[i,j+1])-int(g[i,j]))
# self.imgarray[:,:,0]=self.imgarray[:,:,1]
# self.imgarray[:,:,2]=self.imgarray[:,:,1]
self.imgarray[:,:,0]=g
self.imgarray[:,:,1]=g
self.imgarray[:,:,2]=g
self.canvas_draw()
return
# # sobel算子的实现
def sobel(self):
s_suanziX = np.array([[-1,0,1],[-2,0,2],[-1,0,1]]) # X方向
s_suanziY = np.array([[-1,-2,-1],[0,0,0],[1,2,1]])
for i in range(self.h-2):
for j in range(self.w-2):
new_imageX = abs(np.sum(self.imgarray[i:i+3, j:j+3,1] * s_suanziX))
new_imageY = abs(np.sum(self.imgarray[i:i+3, j:j+3,1] * s_suanziY))
self.imgarray[i, j,1] = (new_imageX*new_imageX + new_imageY*new_imageY)**0.5
self.imgarray[:,:,0]=self.imgarray[:,:,1]
self.imgarray[:,:,2]=self.imgarray[:,:,1]
self.canvas_draw()
return
# Laplace算子
# 常用的Laplace算子模板 [[0,1,0],[1,-4,1],[0,1,0]] [[1,1,1],[1,-8,1],[1,1,1]]
def laplace(self):
L_suanzi = np.array([[0,-1,0],[-1,4,-1],[0,-1,0]])
# L_sunnzi = np.array([[1,1,1],[1,-8,1],[1,1,1]])
# for i in range(self.h-2):
# for j in range(self.w-2):
# self.imgarray[i, j,1] = abs(np.sum( L_suanzi*self.imgarray[i:i+3, j:j+3,1] ))
g=self.imgarray[:,:,1]
for i in range(1,g.shape[0]-1):
for j in range(1,g.shape[1]-1):
g[i-1,j-1]=abs(4*int(g[i,j])-int(g[i-1,j])-int(g[i,j+1])-int(g[i+1,j])-int(g[i,j-1]))
if g[i-1,j-1]>255:
g[i-1,j-1]=255
self.imgarray[:,:,1]=g
self.imgarray[:,:,0]=self.imgarray[:,:,1]
self.imgarray[:,:,2]=self.imgarray[:,:,1]
self.canvas_draw()
return
def histogram_match(self): #直方图均衡化处理
self.imgarray=np.array(self.photo)
r=np.zeros(256)
g=np.zeros(256)
b=np.zeros(256)
tempr=np.zeros(256)
tempg=np.zeros(256)
tempb=np.zeros(256)
tr=np.zeros(256)
tg=np.zeros(256)
tb=np.zeros(256)
for i in range(self.imgarray.shape[0]):
for j in range(self.imgarray.shape[1]):
r[self.imgarray[i][j][0]]+=1
g[self.imgarray[i][j][1]]+=1
b[self.imgarray[i][j][2]]+=1
r=r/(self.w*self.h)
g=g/(self.w*self.h)
b=b/(self.w*self.h)
tempr[0]=r[0]
tempg[0]=g[0]
tempb[0]=b[0]
for i in range(1,256):
tempr[i]=tempr[i-1]+r[i]
tempg[i]=tempg[i-1]+g[i]
tempb[i]=tempb[i-1]+b[i]
tr[i]=int(tempr[i]*255+0.5)
tg[i]=int(tempg[i]*255+0.5)
tb[i]=int(tempb[i]*255+0.5)
for i in range(self.imgarray.shape[0]):
for j in range(self.imgarray.shape[1]):
self.imgarray[i][j][0]=tr[self.imgarray[i][j][0]]
self.imgarray[i][j][1]=tg[self.imgarray[i][j][1]]
self.imgarray[i][j][2]=tb[self.imgarray[i][j][2]]
self.canvas_draw()
return
def contrast_bright(self): #对比度
stk=tk.Tk()
stk.title(‘对比度和亮度调整’)
stk.geometry(‘200×100’)
yr= np.array(self.imgarray[:,:,0])#创建新的数组,值为self.imgarray[:,:,0]
yg= np.array(self.imgarray[:,:,1])
yb= np.array(self.imgarray[:,:,2])
thredr=np.mean(yr)
thredg=np.mean(yg)
thredb=np.mean(yb)
def getval(super):
cnum=int(s1.get())
bnum=int(s2.get())
r,g,b=(yr,yg,yb)
#(像素值-像素均值)*对比度系数+像素均值*明亮度系数
r=r+np.trunc((r-thredr)*cnum/255+thredr*bnum/255)
g=g+np.trunc((r-thredg)*cnum/255+thredg*bnum/255)
b=b+np.trunc((r-thredb)*cnum/255+thredb*bnum/255)
for i in [r,g,b]:
i[i>255]=255
i[i<0]=0
self.imgarray[:,:,0]=r
self.imgarray[:,:,1]=g
self.imgarray[:,:,2]=b
self.canvas_draw()
return
tk.Label(stk, text=”对比度:”).grid(row=0, column=0, padx=5, pady=5, sticky=’W’)
s1=tk.Scale(stk,length=120, command=getval,from_=-255, to=255,orient=”horizontal”,relief=’flat’)
s1.grid(row=0, column=1)
tk.Label(stk,text=’亮 度:’).grid(row=1, column=0, padx=5, pady=5, sticky=’W’)
s2 = tk.Scale(stk,length=120, command=getval,from_=-255, to=255,orient=”horizontal”,relief=’flat’)
s2.grid(row=1, column=1)
stk.mainloop()
return
def brightness(self):
pass
def gray(self): #彩色图像灰度化处理
#self.imgarray=np.array(self.photo)
# for i in range(self.imgarray.shape[0]):
# for j in range(self.imgarray.shape[1]):
# c=self.imgarray[i][j][0]*0.3+self.imgarray[i][j][1]*0.6+self.imgarray[i][j][2]*0.1
# self.imgarray[i][j][0]=c
# self.imgarray[i][j][1]=c
# self.imgarray[i][j][2]=c
c=self.imgarray[:,:,0]*0.3+self.imgarray[:,:,1]*0.6+self.imgarray[:,:,2]*0.1
c=np.trunc(c) #将元素值取整
# a = np.reshape(c,(c.shape[0],c.shape[1],1))#将二维矩阵转为一层的三维矩阵
# self.imgarray= np.concatenate([a,a,a],2)#将3个三维矩阵按照第三轴叠加
self.imgarray[:,:,0]=c
self.imgarray[:,:,2]=c
self.imgarray[:,:,1]=c
self.canvas_draw()
return
def binProc(self):#阈值二值化
threshold=askdiag.askinteger(‘阈值二值化’,’输入二分阈值’,initialvalue=128)
g=self.imgarray[:,:,1]
g[g>threshold ]=255
g[g<threshold]=0
self.imgarray[:,:,0]=g
self.imgarray[:,:,1]=g
self.imgarray[:,:,2]=g
self.canvas_draw()
pass
def hist(self): #彩色直方图
histtk=tk.Tk()
histtk.title(‘彩色直方图’)
histtk.geometry(‘900×300’)
canvas=tk.Canvas(histtk, width=900,height=300)
canvas.pack(fill = ‘both’,expand =’yes’)
canvas.create_text(100,20, text=str(‘R’))
canvas.create_text(400,20, text=str(‘G’))
canvas.create_text(700,20, text=str(‘B’))
canvas.create_rectangle(10,30,265,280)
canvas.create_rectangle(300,30,555,280)
canvas.create_rectangle(600,30,855,280)
# photo= Image.open(‘3d水滴.jpg’) #加载的图像
self.imgarray=np.array(self.photo)
r=np.zeros(256)
g=np.zeros(256)
b=np.zeros(256)
x=np.arange(0,256)
for i in range(self.imgarray.shape[0]):
for j in range(self.imgarray.shape[1]):
r[self.imgarray[i][j][0]]+=1
g[self.imgarray[i][j][1]]+=1
b[self.imgarray[i][j][2]]+=1
r=r/np.max(r)
r=np.int_(r*250)
g=g/np.max(g)
g=np.int_(g*250)
b=b/np.max(b)
b=np.int_(b*250)
for i in range(256):
canvas.create_line(10+x[i],280,10+x[i],280-r[i],width=1,fill=’red’)
canvas.create_line(300+x[i],280,300+x[i],280-g[i],width=1,fill=’green’)
canvas.create_line(600+x[i],280,600+x[i],280-b[i],width=1,fill=’blue’)
for i in range(0,201,50):
canvas.create_text(10+x[i],290, text=str(x[i]))
canvas.create_text(300+x[i],290, text=str(x[i]))
canvas.create_text(600+x[i],290, text=str(x[i]))
canvas.create_text(10+255,290, text=str(255))
canvas.create_text(300+255,290, text=str(255))
canvas.create_text(600+255,290, text=str(255))
pass
def binProc2(self): #阈值区间二值化
hk=tk.Tk()
hk.title(‘阈值区间二值化’)
hk.geometry(‘200×100’)
lab1 = tk.Label(hk, text=”值1:”)
lab1.grid(row=0, column=0, padx=5, pady=5, sticky=’W’)
low = tk.IntVar()#绑定对象到Entry
ent1 = tk.Entry(hk, textvariable=low)
ent1.grid(row=0, column=1, sticky=’ew’, columnspan=2)
lab2 = tk.Label(hk, text=”值1:”)
lab2.grid(row=1, column=0, padx=5, pady=5, sticky=’W’)
high = tk.IntVar() #绑定对象到Entry
ent2 = tk.Entry(hk, textvariable=high)
ent2.grid(row=1, column=1, sticky=’ew’, columnspan=2)
def on_click():
for i in range(self.imgarray.shape[0]):
for j in range(self.imgarray.shape[1]):
c=self.imgarray[i][j][1] #以G分量为基础进行阈值区间二值化
if c>=int(ent1.get()) and c<=int(ent2.get()):
c=255
else:
c=0
self.imgarray[i][j][0]=c
self.imgarray[i][j][1]=c
self.imgarray[i][j][2]=c
self.canvas_draw()
hk.quit()
hk.destroy()
return
bntok=tk.Button(hk,text=’确定’,command=on_click)
bntok.grid(row=2, column=1)
hk.mainloop()
return
def openfile(self):
filetype = [(‘JPGE Files’, ‘*.jpg’),
(‘PNG Files’, ‘*.png’),
(‘All Files’, ‘*.*’)]
filename = tkfd.askopenfilename(filetypes = filetype)
self.photo= Image.open(filename) #加载的图像
self.imgarray=np.array(self.photo)#图像数据转换为数组
self.w,self.h=self.photo.size #获得图像实际大小
self.canvas_draw()#绘制图像
return
def savefile(self):
filetype = [(‘JPGE Files’, ‘*.jpg’),
(‘PNG Files’, ‘*.png’),]
filename=tk.StringVar()
filepath=tkfd.asksaveasfilename(filetypes = filetype,defaultextension=’.png’)
filename.set(filepath)
img= Image.fromarray(self.imgarray.astype(‘uint8’))
img.save(str(filename.get()))
return
def exitsys(self):
self.quit()
self.destroy()
pass
def canvas_draw(self):
if self.w>640 and self.h>480:
width=640 #尺寸大于640*480的以640*480大小显示
high=480
elif self.w>640 and self.h<=480:
rat=self.w/self.h #宽大于640,高对应缩放
width=640
high=int(640/rat)
elif self.w<=640 and self.h>480:
rat=self.w/self.h #高大于480,宽对应缩放
width=int(480*rat)
high=480
else:
width=self.w
high=self.h
#numpy数组数据转换为PIL.Image形式
self.photo= Image.fromarray(self.imgarray.astype(‘uint8’)).convert(‘RGB’)
resizeimg =self.photo.resize((width,high)) # 规定显示图片大小为640*480
self.canvasimg = ImageTk.PhotoImage(resizeimg)
#更新画布图像数据
self.canvas.itemconfig(self.canvas_on_image,image=self.canvasimg)
return
if __name__==’__main__’:
w=window()
w.mainloop()
”’
给个photoshop调节对比度的公式,
nRGB = RGB + (RGB – Threshold) * Contrast / 255
其中nRGB代表了r,g,b各自重新计算后的值。Threshold是平均亮度,一般我们不会特意算图像的平均亮度,一来耗时,二来大部分图片是在100~150之间。我们取127,与实际相近。Contrast取值范围为[-255,255]。
所以当Contrast为0时,rgb值不变,表示当前的一个对比度。
为-255时,rgb都为127,亮度都一样,没有差别,呈灰色。
为255时,在Threshold之上的像素点会变得更亮,反之变得更暗。
”’
加载图像
图像灰度化等处理
直方图
图像对比度,亮度和边缘算子处理