利用opencv以及easygui实现简易的多功能小程序(二)
import numpy as npfrom 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 =
else:
connect =
return connect
def gray_distance(image,point1,point2): #返回灰度值之间的差异,太大的我们舍弃
return abs(int(image)-int(image))
def seed_growing(image):
thresh = 3
#我们自己设置的门限
label1 = 1 #label = 1这样的话图像中为黑色,容易发现
seed = #定义初始种子点
image = image[:, :, 0] * 0.11 + image[:, :, 1] * 0.59 + image[:, :, 2] * 0.3
image = image.astype(np.uint8)
rows = image.shape
cols = image.shape
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 = label1
for i in range(8): #因为我定义的P为1 所以是8个点,p=0则有四个点
tempX = seed_testing.x + connects.x
tempY = seed_testing.y + connects.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 == 255:
seedlist.append(Point(tempX,tempY))
image_mark = 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
cols = image.shape
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) < medium_number:
image2 = 0
min_area += 1
else:
image2 = 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) < medium_number:
# image3 = 0
# min_area += 1
# else:
# image3 = 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
cols = image.shape
sum2 = []
for i in range(rows):
for j in range(cols):
sum2.append(int(image))
sum2.sort()
medium_number = sum2 #去中位数的灰度值
min_area = 0
max_area = 0
area = rows * cols
for i in range(rows):
for j in range(cols):
if int(image) < medium_number:
image = 0
min_area +=1
else:
image = 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
cols = image.shape
sum1=[]
for i in range(rows):
for j in range(cols):
sum1.append(int(image))
sum_average = sum(sum1)/len(sum1)
var_sum=[]
for i in range(rows):
for j in range(cols):
var_sum.append(image**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):
for j in range(image.shape):
for k in range(image.shape):
a.append(image)
if image > r_max:
r_max = image
if image < r_min:
r_min = image
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, image.shape, 3), dtype=np.float32)
for i in range(image.shape):
for j in range(image.shape):
for k in range(image.shape):
precewise_img = k2 * (image - r1)
b.append(precewise_img)
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): #没做灰度变换
# for j in range(image.shape):
# for k in range(image.shape):
# if image > r_max:
# r_max = image
# if image < r_min:
# r_min = image
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, image.shape, 3), dtype=np.float32)
for i in range(image.shape):
for j in range(image.shape):
for k in range(image.shape):
if r1 <= image <= r2:
precewise_img = k2 * (image - r1)
elif image < r1:
precewise_img = k1 * image
elif image > r2:
precewise_img = k3 * (image - 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
cols = image.shape
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#此时类型a为np.uint8,转化为array类型方便后续计算
a=np.array(a)
a=np.sort(a.reshape(-1))
line.append(a) #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=0
else:
NoiseImg=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
cols = NoiseImg.shape
rows,cols=NoiseImg.shape
for i in range(rows):
for j in range(cols):
NoiseImg=NoiseImg+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<0:
NoiseImg = 0
elif NoiseImg>255:
NoiseImg = 255
cv.imshow('guasenoise image', NoiseImg)
cv.waitKey(1000)
def salt(image1,number): #number表述噪声点数量
image = image1.copy()
rows= image.shape
cols = image.shape
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 = 255
else:
image = 0
return image
def convolution(kernal_size, image):
rows=image.shape
cols = image.shape
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
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
页:
[1]