利用opencv以及easygui实现简易视觉系统(二) 包含图像去噪、阈值分割、分段线性拉伸、直方图拉伸、区域生长分割

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import scipy.signal as signal
import cv2 as cv
import random
import easygui as g
import imutils
import time

class Point(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def getX(self):
        return self.x
    def getY(self):
        return self.y
def criterion(p):  #定义我们自己种子生长的准则,p=1为一种规则,p=0为一种生长规则
    if p == 1:
        connect = [Point(-1,-1),Point(-1,0),Point(0,-1),Point(0,1),Point(1,1),Point(1,0),Point(-1,1),Point(1,-1)]
    else:
        connect = [Point(-1,0),Point(0,-1),Point(0,1),Point(1,0)]
    return connect
def gray_distance(image,point1,point2):    #返回灰度值之间的差异,太大的我们舍弃
    return abs(int(image[point1.x,point1.y])-int(image[point2.x,point2.y]))
def seed_growing(image):
    thresh = 3
    #我们自己设置的门限
    label1 = 1    #label = 1这样的话图像中为黑色,容易发现
    seed = [Point(250,100),Point(82,75),Point(20,300)]                #定义初始种子点
    image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    image = image.astype(np.uint8)
    rows = image.shape[0]
    cols = image.shape[1]
    image_mark = np.full((rows,cols),255)
    seedlist = []
    p=1                 #定义我们自己的准则
    connects = criterion(p)
    for i in seed:
        seedlist.append(i)
    while ( len(seedlist) > 0):
        seed_testing = seedlist.pop(0)
        image_mark[seed_testing.x,seed_testing.y] = label1
        for i in range(8):   #因为我定义的P为1 所以是8个点,p=0则有四个点
            tempX = seed_testing.x + connects[i].x
            tempY = seed_testing.y + connects[i].y
            if tempX < 0 or tempY < 0 or tempX >=rows or tempY >= cols:
                continue
            gray_dis = gray_distance(image,seed_testing,Point(tempX,tempY))
            if gray_dis < thresh and image_mark[tempX,tempY] == 255:
                seedlist.append(Point(tempX,tempY))
                image_mark[tempX,tempY] = label1
    cv.imshow('seed grow',image_mark.astype(np.uint8))
    cv.waitKey(0)


def nothing(x):
    pass

def change_number(image):
    image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    rows = image.shape[0]
    cols = image.shape[1]
    min_area = 0
    max_area = 0
    area = rows * cols
    cv.namedWindow('could change threshhold')
    cv.createTrackbar('intensity', 'could change threshhold', 0, 255, nothing)
    count = 0
    # chance =0
    data1 = 699
    data = 0
    while (1):
        cv.imshow('could change threshhold', image) # 返回滑块所在位置对应的值
        medium_number = cv.getTrackbarPos('intensity', 'could change threshhold')
        # if chance == 0:
        image2 =image.copy()
        for i in range(rows):
            for j in range(cols):
                if int(image2[i, j]) < medium_number:
                    image2[i, j] = 0
                    min_area += 1
                else:
                    image2[i, j] = 255
                    max_area += 1
        image2 = image2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
        cv.imshow('image2',image2)
        data +=1
        if data ==8:   #设置我们自己的时钟,按Q退出
            string = 'gray area is {},white area is {}'.format(min_area * area / (min_area + max_area),max_area * area / (min_area + max_area))
            print(string)
            data = 0
        # data +=1
        # if data == 2:
            # if data1 != medium_number:
            #     data1 = medium_number
            #     count = 0
            # else:
            #     count +=1
            #     if count == 2:
                    # image3 = image.copy()
                    # for i in range(rows):
                    #     for j in range(cols):
                    #         if int(image3[i, j]) < medium_number:
                    #             image3[i, j] = 0
                    #             min_area += 1
                    #         else:
                    #             image3[i, j] = 255
                    #             max_area += 1
                    # image3 = image3.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
            # string = 'gray area is {},white area is {}'.format(min_area * area / (min_area + max_area),max_area * area / (min_area + max_area))
            # print(string)
            # count =0
        # data = 0
        # chance +=1
        if cv.waitKey(1) == ord('q'):
            break
    cv.destroyAllWindows()


def static_number(image):   #也进行灰度化
    image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    rows = image.shape[0]
    cols = image.shape[1]
    sum2 = []
    for i in range(rows):
        for j in range(cols):
            sum2.append(int(image[i, j]))
    sum2.sort()
    medium_number = sum2[len(sum2)//2]     #去中位数的灰度值
    min_area = 0
    max_area = 0
    area = rows * cols
    for i in range(rows):
        for j in range(cols):
            if int(image[i,j]) < medium_number:
                image[i,j] = 0
                min_area +=1
            else:
                image[i,j] = 255
                max_area +=1
    image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    g.msgbox('灰色区域面积为{0},白色面积为{1}'.format(min_area * area /(min_area+max_area),max_area * area/(min_area+max_area) ))
    cv.imshow('static number image',image)
    cv.waitKey(0)



def myvar(image):   #将输入图片转换为灰度图
    image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    rows = image.shape[0]
    cols = image.shape[1]
    sum1=[]
    for i in range(rows):
        for j in range(cols):
            sum1.append(int(image[i,j]))
    sum_average = sum(sum1)/len(sum1)
    var_sum=[]
    for i in range(rows):
        for j in range(cols):
            var_sum.append(image[i,j]**2/len(sum1))
    var = sum(var_sum) - sum_average**2
    return var



def hist_stretch(image):     #没做灰度变换
    r_min, r_max = 255, 0
    a=[]
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            for k in range(image.shape[2]):
                a.append(image[i,j,k])
                if image[i, j, k] > r_max:
                    r_max = image[i, j, k]
                if image[i, j, k] < r_min:
                    r_min = image[i, j, k]
    a=np.array(a).reshape(-1)
    a_var=np.var(a)
    r1, s1 = r_min, 0
    r2, s2 = r_max, 255  # 这四个值决定了分段函数的走向
    # k1 = s1 / r1
    # k3 = (255 - s2) / (255 - r2)
    k2 = (s2 - s1) / (r2 - r1)     #255 * (最大灰度值-最小灰度值)

    b=[]
    precewise_img = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32)
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            for k in range(image.shape[2]):
                precewise_img[i, j, k] = k2 * (image[i, j, k] - r1)
                b.append(precewise_img[i,j,k])
    b = np.array(b).reshape(-1,1)
    b_var = np.var(b)
    # g.msgbox('变换前的方差为{},变换后的方差为{}'.format(int(a),int(b)))
    print(a)
    print(b)
    # 原图中做分段线性变化后需要对图像进行归一化操作,并将数据类型转换到np.uint8
    cv.normalize(precewise_img, precewise_img, 0, 255, cv.NORM_MINMAX)
    precewise_img = cv.convertScaleAbs(precewise_img)
    g.msgbox('处理前的图片方差为{one},处理后的方差为{two}'.format(one=myvar(image), two=myvar(precewise_img)))

    cv.imshow('origin image', imutils.resize(image, 480))
    cv.imshow('hist_stretch image', imutils.resize(precewise_img, 480))
    if cv.waitKey(0) == 27:
        cv.destroyAllWindows()

def muti_liner_stretch(image):                #s1,s2分别为灰度级上的两个边界,#该分段线性拉伸法,将灰度级分成三分,一份小于最小灰度级,一份大于最大灰度级,这两部分无定义,直接映射中间部分
    # r_min, r_max = 255, 0
    # for i in range(image.shape[0]):               #没做灰度变换
    #     for j in range(image.shape[1]):
    #         for k in range(image.shape[2]):
    #             if image[i, j, k] > r_max:
    #                 r_max = image[i, j, k]
    #             if image[i, j, k] < r_min:
    #                 r_min = image[i, j, k]
    r1, s1 = 50,100
    r2, s2 = 170,200      #这四个值决定了分段函数的走向
    k1 = s1 / r1
    k3 = (255 - s2) / (255 - r2)
    k2 = (s2 - s1) / (r2 - r1)

    precewise_img = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.float32)
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            for k in range(image.shape[2]):
                if r1 <= image[i, j, k] <= r2:
                    precewise_img[i, j, k] = k2 * (image[i, j, k] - r1)
                elif image[i, j, k] < r1:
                    precewise_img[i, j, k] = k1 * image[i, j, k]
                elif image[i, j, k] > r2:
                    precewise_img[i, j, k] = k3 * (image[i, j, k] - r2)

    # 原图中做分段线性变化后需要对图像进行归一化操作,并将数据类型转换到np.uint8
    cv.normalize(precewise_img, precewise_img, 0, 255, cv.NORM_MINMAX)
    precewise_img = cv.convertScaleAbs(precewise_img)
    g.msgbox('处理前的图片方差为{one},处理后的方差为{two}'.format(one=myvar(image),two=myvar(precewise_img)))    #函数本身没做灰度化,但是求方差时我做了灰度化
    cv.imshow('origin image', imutils.resize(image, 480))
    cv.imshow('muti_liner_stretch image', imutils.resize(precewise_img, 480))
    if cv.waitKey(0) == 27:
        cv.destroyAllWindows()
def medium_filter(image):  #中值滤波模板为3*3
    image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    # kernal_size=np.ones((3,3))
    rows=image.shape[0]
    cols = image.shape[1]
    gray_data = image.copy()
    img_new = []
    for i in range(rows-3):   #减去3的原因是自己定义的模板都是3*3
        line = []             #line记录着每一行的信息
        for j in range(cols-3):
            a = gray_data[i:i+3,j:j+3]  #此时类型a为np.uint8,转化为array类型方便后续计算
            a=np.array(a)
            a=np.sort(a.reshape(-1))
            line.append(a[4])   #np.multiply表示两个矩阵点乘
        img_new.append(line)   #记录着每一行卷积后的结果
    image2=np.array(img_new)
    image2 = (image2 / float(image2.max())) * 255

 # 显示图像
    plt.subplot(2,1,1)
    plt.title('original image')
    plt.imshow(image,cmap=cm.gray)
    plt.axis("off")
    plt.subplot(2,1,2)
    plt.title('after medium image')
    plt.imshow(image2,cmap=cm.gray)
    plt.axis("off")
    plt.show()

def PepperandSalt(image,percentage):   # percentage表示噪声点出现的概率    #进来的第一步是灰度化
    # R = np.mat(image[:, :, 0])
    # G = np.mat(image[:, :, 1])
    # B = np.mat(image[:, :, 2])
    # img_gray2 = R * 0.299 + G * 0.587 + B * 0.114
    img_gray2 = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    img_gray2 = img_gray2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    NoiseImg=img_gray2
    rows,cols=NoiseImg.shape
    NoiseNum=int(percentage*rows*cols)
    for i in range(NoiseNum):
        randX=np.random.randint(0,rows)
        randY=np.random.randint(0,cols)
        if random.randint(0,1) == 0:
            NoiseImg[randX,randY]=0
        else:
            NoiseImg[randX,randY]=255
    cv.imshow('Peppernoise image', NoiseImg)
    cv.waitKey(1000)

def GaussianNoise(image,mean,sigma):     #mean表示均值,sigma表示方差    #第一步是灰度化
    # R=np.mat(image[:,:,0])
    # G=np.mat(image[:,:,1])
    # B=np.mat(image[:,:,2])
    # img_gray2 = R*0.299+G*0.587+B*0.114
    img_gray2 = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    img_gray2 = img_gray2.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    NoiseImg=img_gray2
    rows = NoiseImg.shape[0]
    cols = NoiseImg.shape[1]
    rows,cols=NoiseImg.shape
    for i in range(rows):
        for j in range(cols):
            NoiseImg[i,j]=NoiseImg[i,j]+random.gauss(mean,sigma)
    # NoiseImg = NoiseImg+np.random.normal(mean,sigma,NoiseImg.shape)
    # NoiseImg =  NoiseImg - np.full( NoiseImg.shape, np.min( NoiseImg))     # 全填充限定像素值下限(减去最小值,下限重新定义为0)
    # NoiseImg =  NoiseImg * 255 / np.max( NoiseImg)               #限定像素值上限
            if NoiseImg[i,j]<0:
                NoiseImg[i,j] = 0
            elif NoiseImg[i,j]>255:
                NoiseImg[i,j] = 255
    cv.imshow('guasenoise image', NoiseImg)
    cv.waitKey(1000)

def salt(image1,number):      #number表述噪声点数量
    image = image1.copy()
    rows= image.shape[0]
    cols = image.shape[1]
    for i in range(number):
        x=np.random.randint(0,rows)   #np.ranom.randint 取不到右边界,ranodm.randint取得到右边界
        y=np.random.randint(0,cols)
        c=random.randint(0,1)
        if c == 1:
            image[x,y] = 255
        else:
            image[x,y] = 0
    return image
def convolution(kernal_size, image):
    rows=image.shape[0]
    cols = image.shape[1]
    gray_data = image.copy()
    img_new = []
    for i in range(rows-3):   #减去3的原因是自己定义的模板都是3*3
        line = []             #line记录着每一行的信息
        for j in range(cols-3):
            a = gray_data[i:i+3,j:j+3]
            a=np.array(a)
            line.append(np.sum(np.multiply(kernal_size, a)))   #np.multiply表示两个矩阵点乘
        img_new.append(line)   #记录着每一行卷积后的结果
    return np.array(img_new)
def mean_image(image):                  #均值滤波     #进来的第一不也是灰度化
    suanzi = np.ones((3,3))/9 # 创建全1算子(1/9)
    # 打开图像并转化成灰度图像
    image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    image2 = convolution(image=image,kernal_size=suanzi)
    # 将结果灰度值转化到0-255
    image2 = (image2/float(image2.max()))*255
    image3=cv.blur(image,(5,5))

    # 显示图像
    plt.subplot(3,1,1)
    plt.title('original image')
    plt.imshow(image,cmap=cm.gray)
    plt.axis("off")
    plt.subplot(3,1,2)
    plt.title('after meaning image')
    plt.imshow(image2,cmap=cm.gray)
    plt.axis("off")
    plt.subplot(3, 1, 3)
    plt.title('function made')
    plt.imshow(image3, cmap=cm.gray)
    plt.axis("off")
    plt.show()
def func(x,y,sigma=1):
    return 100*(1/(2*np.pi*sigma))*np.exp(-((x-1)**2+(y-1)**2)/(2.0*sigma**2))   #创建高斯函数,该函数中心为(1,1),所以创建3*3比较合适

def gause_image(image):             #高斯滤波,第一步也实现了灰度化
    suanzi = np.fromfunction(func,(3,3),sigma=2)  # 创建高斯函数,(1,1)为函数的中心,这里是生成3*3的标准差为2的高斯算子
    # 打开图像并转化成灰度图像
    image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
    image = image.astype(np.uint8)  # GRAY=0.3*R+0.59*G+0.11*B:
    image2 = convolution(image=image, kernal_size=suanzi)
    # 将结果灰度值转化到0-255
    image2 = (image2 / float(image2.max())) * 255

    # 显示图像
    plt.subplot(2, 1, 1)
    plt.title('original image')
    plt.imshow(image, cmap=cm.gray)
    plt.axis("off")
    plt.subplot(2, 1, 2)
    plt.title('after gause image')
    plt.imshow(image2, cmap=cm.gray)
    plt.axis("off")
    plt.show()
if __name__ == '__main__':
    # image1 = cv.imread('D:\\test.jpg')  #读取我们的照片
    # # image_salt = salt(image,2000)       #加入噪声
    # # mean_image(image_salt)
    # # gause_image(image_salt)
    # GaussianNoise(image1, mean=2, sigma=14)
    # cv.imshow('salt image', PepperandSalt(image1, percentage=0.01))
    msg = "请输入您想要完成的任务(建议您第一步先打开图片)"
    title = '第二次作业'
    choice = ('打开图片', '退出')
    a = g.buttonbox(msg=msg, title=title, choices=choice)
    if a == '打开图片':
        filename = g.fileopenbox(msg="请打开一个jpg文件")
        img = cv.imread(filename)
        msg1 = "选择您想要实现的功能"
        title1 = '第二次作业'
        choice1 = ('显示噪声图', '滤波', '阈值分割', '分段线性法拉伸', '直方图拉伸', '区域生长法分割','重新选择图片','退出')
        q = 1
        while q:
            b = g.buttonbox(msg=msg1, title=title1, choices=choice1)
            # while b!='退出':
            if b == '显示噪声图':
                msg2 = "选择您想要实现的功能"
                title2 = '第二次作业'
                choice2 = ('灰色椒盐噪声图', '灰色高斯噪声图','退出')
                q1=1
                while q1:
                    noise_image_choice = g.buttonbox(msg=msg2, title=title2, choices=choice2)
                    if noise_image_choice == '灰色椒盐噪声图':
                        PepperandSalt(img, percentage=0.01) #这里设置椒盐噪声点出现的概率为0.01
                    elif noise_image_choice == '灰色高斯噪声图':
                        GaussianNoise(img, mean=2, sigma=14) #这里设置均值为2,方差为4
                    else:
                        q1 =0

            elif b == '滤波':
                msg_b = "选择您想要实现的功能"
                title_b = '第二次作业'
                choice_b = ('均值滤波', '高斯滤波','中值滤波')
                q_b = 1
                while q_b:
                    b_remove_noise = g.buttonbox(msg=msg_b, title=title_b, choices=choice_b)
                    if b_remove_noise == '均值滤波':
                        mean_image(salt(img,number=5000))          #salt为自己定义的可以随意增加噪声点的函数,number为自己定义噪声点的数量
                    elif b_remove_noise =='高斯滤波':
                        gause_image(salt(img,number=5000))
                    elif b_remove_noise == '中值滤波':
                        medium_filter(salt(img,number=5000))
                    else:
                        q_b = 0

            elif b == '阈值分割':
                msg_b1 = "选择您想要实现的功能"
                title_b1 = '第二次作业'
                choice_b1 = ('固定阈值', '调节参数窗')
                q_b1 = 1
                while q_b1:
                    b_remove_noise1 = g.buttonbox(msg=msg_b1, title=title_b1, choices=choice_b1)
                    if b_remove_noise1 == '固定阈值':
                        static_number(img)
                    elif b_remove_noise1 == '调节参数窗':
                        change_number(img)
                    else:
                        q_b1 = 0

            elif b == '分段线性法拉伸':
                muti_liner_stretch(img)
            elif b == '直方图拉伸':
                hist_stretch(img)
            elif b == '区域生长法分割':
                seed_growing(img)
            elif b == '重新选择图片':
                filename = g.fileopenbox(msg="请打开一个jpg文件")
                img = cv.imread(filename)
            else:
                q = 0
```python
在这里插入代码片

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值