# -*- 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之上的像素点会变得更亮,反之变得更暗。
”’

加载图像

图像灰度化等处理

 

 直方图

 

图像对比度,亮度和边缘算子处理


版权声明:本文为nc_yhy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/nc_yhy/article/details/119089029