正常图像
有缺陷图像
目的是区分判断出有缺陷的图像。但是,本项目有一些比较困难的点,例如(1),光照或噪声会有变化;(2),有时关键区域位置上会有小的变化
LBP是一种可以解决光照变化和旋转变化的特征向量,是否要用LBP进行特征提取?以下是LBP特征提取的代码:
在图像匹配方面,因为主要观测图像结构的差异,如果是噪声或光照的变化需要忽略,所以我们用到了SSIM来计算图像直接的相似度。
# 以下不再重复这个部分
import cv2
import numpy as np
def origin_LBP(img):
dst = np.zeros(img.shape,dtype=img.dtype)
h,w=img.shape
start_index=1
for i in range(start_index,h-1):
for j in range(start_index,w-1):
center = img[i][j]
code = 0
# 顺时针,左上角开始的8个像素点与中心点比较,大于等于的为1,小于的为0,最后组成8位2进制
code |= (img[i-1][j-1] >= center) << (np.uint8)(7)
code |= (img[i-1][j ] >= center) << (np.uint8)(6)
code |= (img[i-1][j+1] >= center) << (np.uint8)(5)
code |= (img[i ][j+1] >= center) << (np.uint8)(4)
code |= (img[i+1][j+1] >= center) << (np.uint8)(3)
code |= (img[i+1][j ] >= center) << (np.uint8)(2)
code |= (img[i+1][j-1] >= center) << (np.uint8)(1)
code |= (img[i ][j-1] >= center) << (np.uint8)(0)
dst[i-start_index][j-start_index]= code
return dst
def circular_LBP(img, radius=3, neighbors=8):
h,w=img.shape
dst = np.zeros((h-2*radius, w-2*radius),dtype=img.dtype)
for i in range(radius,h-radius):
for j in range(radius,w-radius):
# 获得中心像素点的灰度值
center = img[i,j]
for k in range(neighbors):
# 计算采样点对于中心点坐标的偏移量rx,ry
rx = radius * np.cos(2.0 * np.pi * k / neighbors)
ry = -(radius * np.sin(2.0 * np.pi * k / neighbors))
# 为双线性插值做准备
# 对采样点偏移量分别进行上下取整
x1 = int(np.floor(rx))
x2 = int(np.ceil(rx))
y1 = int(np.floor(ry))
y2 = int(np.ceil(ry))
# 将坐标偏移量映射到0-1之间
tx = rx - x1
ty = ry - y1
# 根据0-1之间的x,y的权重计算公式计算权重,权重与坐标具体位置无关,与坐标间的差值有关
w1 = (1-tx) * (1-ty)
w2 = tx * (1-ty)
w3 = (1-tx) * ty
w4 = tx * ty
# 根据双线性插值公式计算第k个采样点的灰度值
neighbor=img[i+y1,j+x1] * w1 + img[i+y2,j+x1] *w2 + img[i+y1,j+x2] * w3 +img[i+y2,j+x2] *w4
# LBP特征图像的每个邻居的LBP值累加,累加通过与操作完成,对应的LBP值通过移位取得
dst[i-radius,j-radius] |= (neighbor>center) << (np.uint8)(neighbors-k-1)
return dst
# 先对像素分割,用一个小区域的平均值代替这个区域,再用LBP特征处理
def multi_scale_block_LBP(img, scale):
h, w = img.shape
# cellSize表示一个cell大小
cellSize = int(scale / 3)
offset = int(cellSize / 2)
cellImage = np.zeros((h - 2 * offset, w - 2 * offset), dtype=img.dtype)
for i in range(offset, h - offset):
for j in range(offset, w - offset):
temp = 0
for m in range(-offset, offset + 1):
for n in range(-offset, offset + 1):
temp += img[i + n, j + m]
# 即取一个cell里所有像素的平均值
temp /= (cellSize * cellSize)
cellImage[i - offset, j - offset] = np.uint8(temp)
# 再对平均后的像素做LBP特征处理
dst = origin_LBP(cellImage)
return dst
####
def ssim(img1, img2):
C1 = (0.01 * 255) ** 2
C2 = (0.03 * 255) ** 2
img1 = img1.astype(np.float64)
img2 = img2.astype(np.float64)
kernel = cv2.getGaussianKernel(11, 1.5)
window = np.outer(kernel, kernel.transpose())
mu1 = cv2.filter2D(img1, -1, window)[5:-5, 5:-5] # valid
mu2 = cv2.filter2D(img2, -1, window)[5:-5, 5:-5]
mu1_sq = mu1 ** 2
mu2_sq = mu2 ** 2
mu1_mu2 = mu1 * mu2
sigma1_sq = cv2.filter2D(img1 ** 2, -1, window)[5:-5, 5:-5] - mu1_sq
sigma2_sq = cv2.filter2D(img2 ** 2, -1, window)[5:-5, 5:-5] - mu2_sq
sigma12 = cv2.filter2D(img1 * img2, -1, window)[5:-5, 5:-5] - mu1_mu2
ssim_map = ((2 * mu1_mu2 + C1) * (2 * sigma12 + C2)) / ((mu1_sq + mu2_sq + C1) *
(sigma1_sq + sigma2_sq + C2))
return ssim_map.mean()
def calculate_ssim(img1, img2):
'''calculate SSIM
the same outputs as MATLAB's
img1, img2: [0, 255]
'''
if not img1.shape == img2.shape:
raise ValueError('Input images must have the same dimensions.')
if img1.ndim == 2:
return ssim(img1, img2)
elif img1.ndim == 3:
if img1.shape[2] == 3:
ssims = []
for i in range(3):
ssims.append(ssim(img1, img2))
return np.array(ssims).mean()
elif img1.shape[2] == 1:
return ssim(np.squeeze(img1), np.squeeze(img2))
else:
raise ValueError('Wrong input image dimensions.')
# 读入灰度图
image_path_real='D:/TEDS-master_Multi_JN/preprocessing/guiwai/crop/0/normal_detect/190_0_0_res.jpg'
image_path_fake='D:/TEDS-master_Multi_JN/preprocessing/guiwai/crop/0/normal_detect/190_6_0_res.jpg'
gray_real = cv2.imread(image_path_real, cv2.IMREAD_GRAYSCALE)
gray_fake = cv2.imread(image_path_fake, cv2.IMREAD_GRAYSCALE)
###
gray_real = cv2.GaussianBlur(gray_real,(3,3),cv2.BORDER_DEFAULT)
# LBP处理
org_lbp_real = origin_LBP(gray_real)
org_lbp_fake = origin_LBP(gray_fake)
# circul_1_8_real = circular_LBP(gray_real,1,8)
##the best
circul_3_8_real = circular_LBP(gray_real,3,6)
# # circul_3_6_real = circular_LBP(gray_real,3,6)
# circul_3_6_real = circular_LBP(gray_real,3,8)
##the best
circul_3_8_fake = circular_LBP(gray_fake,3,6)
# org_lbp_dis = circul_3_6_real -circul_3_6_fake
imageA = np.array(org_lbp_real, dtype=np.uint8)
imageB = np.array(org_lbp_fake, dtype=np.uint8)
ss = calculate_ssim(imageA, imageB)
print(ss)
# circul_3_6_real = multi_scale_block_LBP(gray_real,6)
# circul_3_6_fake = multi_scale_block_LBP(gray_fake,3)
# cv2.imshow('img', gray)
# cv2.imshow('org_lbp', org_lbp)
# 若针对视频取图片,delay=k时表示下一帧在kms后选取
# cv2.waitKey(0)
cv2.imwrite('D:/TEDS-master_Multi_JN/preprocessing/guiwai/crop/0/abnormal_detect/11_1015_1_0_real.png',circul_3_8_real)
cv2.imwrite('D:/TEDS-master_Multi_JN/preprocessing/guiwai/crop/0/abnormal_detect/11_1015_1_0_fake.png',circul_3_8_fake)
# cv2.imwrite('D:/TEDS-master_Multi_JN/preprocessing/guiwai/crop/0/abnormal_detect/org_lbp_dis.png',org_lbp_dis)
SSIM(Structural SIMilarity),结构相似性,是一种衡量两幅图像相似度的指标。该指标首先由德州大学奥斯丁分校的图像和视频工程实验室(Laboratory for Image and Video Engineering)提出。
SSIM使用的两张图像中,一张为未经压缩的无失真图像,另一张为失真后的图像。
在超分辨率问题中,一直存在着两个经典的图像质量评价算法。其中一个是PSNR(峰值性噪比),还一个便是SSIM(结构相似性评价)。由于最近有用到SSIM,自己写了个python代码版本的SSIM放在文章最后。
SSIM算法简单介绍
其中ux、uy分别表示图像X和Y的均值,σX、σY分别表示图像X和Y的方差,σXY表示图像X和Y的协方差,即
C1、C2、C3为常数,为了避免分母为0的情况,通常取C1=(K1*L)^2, C2=(K2*L)^2, C3=C2/2, 一般地K1=0.01, K2=0.03, L=255. 则
SSIM取值范围[0,1],值越大,表示图像失真越小.
在实际应用中,可以利用滑动窗将图像分块,令分块总数为N,考虑到窗口形状对分块的影响,采用高斯加权计算每一窗口的均值、方差以及协方差,然后计算对应块的结构相似度SSIM,最后将平均值作为两图像的结构相似性度量,即平均结构相似性MSSIM:
上述这些描述转载于:
https://www.cnblogs.com/vincent2012/archive/2012/10/13/2723152.html
- PSNR算法
psnr是“Peak Signal to Noise Ratio”的缩写,即峰值信噪比,是一种评价图像的客观标准,它具有局限性,一般是用于最大值信号和背景噪音之间的一个工程项目。
from PIL import Image
import numpy
import math
def psnr(img1, img2):
mse = numpy.mean( (img1 - img2) ** 2 )
if mse == 0:
return 100
PIXEL_MAX = 255.0
return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))
img1=Image.open('1.png')
img2=Image.open('2.jpg')
img3=Image.open('3.jpg')
img4=Image.open('4.png')
i1_array = numpy.array(img1)
# print(i1_array.shape)
i2_array = numpy.array(img2)
# print(i2_array.shape)
i3_array = numpy.array(img3)
# print(i3_array.shape)
i4_array = numpy.array(img4)
# print(i4_array.shape)
r23=psnr(i2_array,i3_array)
r24=psnr(i2_array,i4_array)
print(r23)
print(r24)