利用openCV或其他工具编写程序实现对多个产品图片进行缺陷检测并判断产品是否合格。
实现过程
1、编写程序
目标图片如下
根据展示的程序功能编写对应的程序:
第一步,读取显示图像的功能openCV已经提供了函数imread()和imshow(),这一次实验的读取图片与前几次实验有些许不同,首先我们需要先读取一张合格产品图片作为样本,然后再读取所有图片并将其与样本进行比较来完成检测缺陷的功能,代码如下
#-*- coding: utf-8 -*-
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw, ImageFont
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"C:\Windows\Fonts\simhei.ttf", size=14)
font1 = ImageFont.truetype("C:\Windows\Fonts\simhei.ttf", 20, encoding="utf-8")
#样本图片
img_orgin=cv.imread('0.bmp')
#多张产品图片的读取
for i in range(6):
img=cv.imread('{}.bmp'.format(i))
第二步,为了对两张图进行比较与匹配,这里我们需要用到直方图来完成这一功能,首先需要绘制每张图的直方图:
def create_rgb_hist(image):
h, w, c = image.shape
# 创建一个(16*16*16,1)的初始矩阵,作为直方图矩阵
# 16*16*16的意思为三通道每通道有16个bins
rgbhist = np.zeros([16 * 16 * 16, 1], np.float32)
bsize = 256 / 16
for row in range(h):
for col in range(w):
b = image[row, col, 0]
g = image[row, col, 1]
r = image[row, col, 2]
# 人为构建直方图矩阵的索引,该索引是通过每一个像素点的三通道值进行构建
index = int(b / bsize) * 16 * 16 + int(g / bsize) * 16 + int(r / bsize)
# 该处形成的矩阵即为直方图矩阵
rgbhist[int(index), 0] += 1
return rgbhist
第三步,编写比较两张图片的函数,这里就需要用到第二步所编写的直方图绘制函数:
def hist_compare(img1,img2):
hist1 = create_rgb_hist(img1)
# 创建第二幅图的rgb三通道直方图(直方图矩阵)
hist2 = create_rgb_hist(img2)
match = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL)
#通过四舍五入拉开相关性值的差
result='{:.1f}'.format(match)
#检查相关值与返回值
print(match,result)
return result
第四步,比较相关值来判断产品是否合格,并在图像上输出合格、不合格的文本信息:
#str1='不合格' str2='合格'
img=cv.imread('{}.bmp'.format(i))
blur1=cv.cvtColor(img,cv.COLOR_BGR2RGB)
pilblur=Image.fromarray(blur1)
draw=ImageDraw.Draw(pilblur)
result=hist_compare(img_orgin,img)
if result!='1.0':
draw.text((5, 5), str1, (255, 0, 0), font=font1)
blurtext=cv.cvtColor(np.array(pilblur),cv.COLOR_RGB2BGR)
cv.imshow('buhege',blurtext)
cv.waitKey(0)
else:
draw.text((5, 5), str2, (255, 0, 0), font=font1)
blurtext=cv.cvtColor(np.array(pilblur),cv.COLOR_RGB2BGR)
cv.imshow('hege',blurtext)
cv.waitKey(0)
运行结果
问题及解决方法
1、图片的匹配
存在的问题:在刚看到产品的缺陷检测问题时,我首先想到的就是对图像进行像素点比较而忽略了老师所讲的直方图,而在进行像素点比较时却出现了问题,图像0作为合格样本与图像1进行比较发现输出的结果显示图像1为不合格产品,后来想到图像中的产品旋转的问题,又将图片的每个像素点的值加起来求平均值并于样本的平均值进行比较,这时的问题就是求出的值过大,对于产品的合格线不好界定。
解决方法:在我陷入如何缩小平均值的同时不影响结果的问题并上网搜索解决方案时,看到了直方图的绘制,同时也找到了使用直方图对图像进行简单匹配的方法。那就是使用直方图比较函数cv2.compareHist(H1,H2,method),比较方式我选用的相关性比较,这个比较方式取值会更容易。使用相关性比较得到的值越大,相关性越高,最大值为1,最小值为0 。
实验总结
这一次的实验看代码行数似乎很简单,因为它只有短短十几行,但这次实验引入了一个新的概念,也就是图像直方图。图像直方图是反映一个图像像素分布的统计表,其横坐标代表了图像像素的种类,纵坐标代表了每一种颜色值在图像中的像素总数或者占所有像素个数的百分比。在实际应用中,图像直方图在特征提取、图像匹配等方面都有很好的应用。
在我看来,直方图的使用、如何运用直方图来解决问题是这次实验的重点。