缺陷图像匹配的问题_LBP

本文探讨了在图像处理领域,如何利用局部二值模式(LBP)特征和结构相似度指数(SSIM)来应对光照变化和噪声对图像检测的影响。LBP能够抵抗光照变化,而SSIM则用于衡量图像的结构相似度,从而在有缺陷图像的检测中提供帮助。代码示例展示了LBP的实现及SSIM的计算过程,对于图像匹配和质量评估具有指导意义。
摘要由CSDN通过智能技术生成

   

正常图像                                          

有缺陷图像

目的是区分判断出有缺陷的图像。但是,本项目有一些比较困难的点,例如(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)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值