175 lines
6.1 KiB
Python
175 lines
6.1 KiB
Python
import cv2
|
|
import numpy as np
|
|
import random
|
|
from matplotlib import pyplot as plt
|
|
|
|
def basic_global_thresholding(Img,T0=0.1): #输入的图像要求为灰度图像
|
|
'''
|
|
:param Img: 需进行全阈值分割的图像
|
|
:param T0: 迭代终止容差,当相临迭代得到的阈值差小于此值,则终止迭代
|
|
:return: 全阈值
|
|
'''
|
|
G1 = np.zeros(Img.shape, np.uint8) # 定义矩阵分别用来装被阈值T1分开的两部分
|
|
G2 = np.zeros(Img.shape, np.uint8)
|
|
T1 = np.mean(Img)
|
|
diff=255
|
|
while(diff>T0):
|
|
_,G1=cv2.threshold(Img,T1,255,cv2.THRESH_TOZERO_INV) #THRESH_TOZERO 超过thresh的像素不变, 其他设为0
|
|
_,G2=cv2.threshold(Img,T1,255,cv2.THRESH_TOZERO)
|
|
garray1 = np.array(G1)
|
|
garray2 = np.array(G2)
|
|
loc1 = np.where(garray1>0.001) #可以对二维数组操作
|
|
loc2 = np.where(garray2 > 0.001)
|
|
# g1 = list(filter(lambda a: a > 0, G1.flatten()))#只能对一维列表筛选,得到的是一个筛选对象
|
|
# g2 = list(filter(lambda a: a > 0, G2.flatten()))
|
|
ave1=np.mean(garray1[loc1])
|
|
ave2=np.mean(garray2[loc2])
|
|
T2=(ave1+ave2)/2.0
|
|
diff=abs(T2 - T1)
|
|
T1=T2
|
|
return T2
|
|
|
|
|
|
|
|
def moving_threshold(image, num,b=0.5):
|
|
'''
|
|
:param image: 将进行阈值分割的图像,为单通道灰度图像
|
|
:param num: 滑动窗口大小
|
|
:param b: 分割权重比例,灰度值大于b*平均值的像素点将设置为白色
|
|
:return: 滑动平均阈值分割图像
|
|
'''
|
|
width = image.shape[0]
|
|
height = image.shape[1]
|
|
widthStep = width
|
|
data = image.flatten() # 转换成一维向量
|
|
dstdata = data.copy()
|
|
n = float(num)
|
|
m_pre = data[0]/n
|
|
|
|
for i in range(0,height-1):
|
|
for j in range(0,width-1):
|
|
index = i * width + j
|
|
if index < num + 1:
|
|
dif = data[index]
|
|
else:
|
|
dif = int(data[index]) - int(data[index-num-1])
|
|
dif *= 1/n
|
|
m_now = m_pre + dif #m_now存放着当前像素点的滑动平均
|
|
m_pre = m_now
|
|
if data[index] > round(b * m_now): #b是一个阈值权重
|
|
dstdata[index] = 255;
|
|
else:
|
|
dstdata[index] = 0;
|
|
return np.array(dstdata).reshape(width, height)
|
|
|
|
# 自适应中值滤波
|
|
def get_window(res_img, noise_mask, sc, i, j, k):
|
|
listx = []
|
|
|
|
if i - sc >= 0:
|
|
starti = i - sc
|
|
else:
|
|
starti = 0
|
|
if j + 1 <= res_img.shape[1] - 1 and noise_mask[0, j + 1, k] != 0:
|
|
listx.append(res_img[0, j + 1, k])
|
|
if j - 1 >= 0 and noise_mask[0, j - 1, k] != 0:
|
|
listx.append(res_img[0, j - 1, k])
|
|
|
|
if i + sc <= res_img.shape[0] - 1:
|
|
endi = i + sc
|
|
else:
|
|
endi = res_img.shape[0] - 1
|
|
if j + 1 <= res_img.shape[1] - 1 and noise_mask[endi, j + 1, k] != 0:
|
|
listx.append(res_img[endi, j + 1, k])
|
|
if j - 1 >= 0 and noise_mask[endi, j - 1, k] != 0:
|
|
listx.append(res_img[endi, j - 1, k])
|
|
|
|
if j + sc <= res_img.shape[1] - 1:
|
|
endj = j + sc
|
|
else:
|
|
endj = res_img.shape[1] - 1
|
|
if i + 1 <= res_img.shape[0] - 1 and noise_mask[i + 1, endj, k] != 0:
|
|
listx.append(res_img[i + 1, endj, k])
|
|
if i - 1 >= 0 and noise_mask[i - 1, endj, k] != 0:
|
|
listx.append(res_img[i - 1, endj, k])
|
|
|
|
if j - sc >= 0:
|
|
startj = j - sc
|
|
else:
|
|
startj = 0
|
|
if i + 1 <= res_img.shape[0] - 1 and noise_mask[i + 1, 0, k] != 0:
|
|
listx.append(res_img[i + 1, 0, k])
|
|
if i - 1 >= 0 and noise_mask[i - 1, 0, k] != 0:
|
|
listx.append(res_img[i - 1, 0, k])
|
|
|
|
for m in range(starti, endi + 1):
|
|
for n in range(startj, endj + 1):
|
|
if noise_mask[m, n, k] != 0:
|
|
listx.append(res_img[m, n, k])
|
|
listx.sort()
|
|
return listx
|
|
|
|
|
|
def get_window_small(res_img, noise_mask, i, j, k):
|
|
listx = []
|
|
sc = 1
|
|
if i - sc >= 0 and noise_mask[i - 1, j, k] != 0:
|
|
listx.append(res_img[i - 1, j, k])
|
|
|
|
if i + sc <= res_img.shape[0] - 1 and noise_mask[i + 1, j, k] != 0:
|
|
listx.append(res_img[i + 1, j, k])
|
|
|
|
if j + sc <= res_img.shape[1] - 1 and noise_mask[i, j + 1, k] != 0:
|
|
listx.append(res_img[i, j + 1, k])
|
|
|
|
if j - sc >= 0 and noise_mask[i, j - 1, k] != 0:
|
|
listx.append(res_img[i, j - 1, k])
|
|
listx.sort()
|
|
return listx
|
|
|
|
|
|
def restore_image(noise_img, size=4):
|
|
"""
|
|
使用 你最擅长的算法模型 进行图像恢复。
|
|
:param noise_img: 一个受损的图像
|
|
:param size: 输入区域半径,长宽是以 size*size 方形区域获取区域, 默认是 4
|
|
:return: res_img 恢复后的图片,图像矩阵值 0-1 之间,数据类型为 np.array,
|
|
数据类型对象 (dtype): np.double, 图像形状:(height,width,channel), 通道(channel) 顺序为RGB
|
|
"""
|
|
# 恢复图片初始化,首先 copy 受损图片,然后预测噪声点的坐标后作为返回值。
|
|
res_img = np.copy(noise_img)
|
|
|
|
# 获取噪声图像
|
|
noise_mask = get_noise_mask(noise_img)
|
|
|
|
for i in range(noise_mask.shape[0]):
|
|
for j in range(noise_mask.shape[1]):
|
|
for k in range(noise_mask.shape[2]):
|
|
if noise_mask[i, j, k] == 0:
|
|
sc = 1
|
|
listx = get_window_small(res_img, noise_mask, i, j, k)
|
|
if len(listx) != 0:
|
|
res_img[i, j, k] = listx[len(listx) // 2]
|
|
else:
|
|
while (len(listx) == 0):
|
|
listx = get_window(res_img, noise_mask, sc, i, j, k)
|
|
sc = sc + 1
|
|
if sc > 4:
|
|
res_img[i, j, k] = np.mean(listx)
|
|
else:
|
|
res_img[i, j, k] = listx[len(listx) // 2]
|
|
|
|
return res_img
|
|
|
|
if __name__ == '__main__':
|
|
# 读入图像
|
|
srcImage = cv2.imread(r".\img\kennysmall.jpg", 0)
|
|
b=0.65
|
|
dstImage = moving_threshold(srcImage, 11,b)
|
|
plt.subplot(121), plt.imshow(srcImage, "gray")
|
|
plt.title("source image"), plt.xticks([]), plt.yticks([])
|
|
plt.subplot(122), plt.imshow(dstImage, "gray")
|
|
plt.title("processed image"), plt.xticks([]), plt.yticks([])
|
|
plt.show()
|
|
cv2.waitKey(0)
|