螺牙缺陷检测
- 简述
- 去噪
- 椒盐噪声
- 高斯噪声
- 小波变换
- 引导滤波
- 求最大凸包
- 判断曲直
- 全部代码
简述
- 今天收到了一个检测螺牙缺陷的问题,当复习opencv练个手,记录一下基础知识。
- 这里的代码是检测弯曲的,其他缺陷用yolo处理。
- 东家给的图片有的是有干扰的(红框标识),所以要求一下最大凸包。
- 里面很多知识是复习用,最终代码在最后一行,给的101张图片,有2个弯曲度超过0.25,来到了0.33以上
- 有个小技巧可以提高弯直的区分度,这里就不介绍了,需要的私信。
去噪
椒盐噪声
import cv2img = cv2.imread('image.jpg')
median = cv2.medianBlur(img, 5)
cv2.imshow('Median filter', median)
cv2.waitKey(0)
cv2.destroyAllWindows()
高斯噪声
import cv2img = cv2.imread('image.jpg')
gaussian = cv2.GaussianBlur(img, (5,5), 0)
cv2.imshow('Gaussian filter', gaussian)
cv2.waitKey(0)
cv2.destroyAllWindows()
小波变换
import cv2
import pywtimg = cv2.imread('image.jpg', 0)
coeffs = pywt.dwt2(img, 'haar')
cA, (cH, cV, cD) = coeffs
cv2.imshow('Wavelet denoising', pywt.idwt2((cA, (None, None, None)), 'haar'))
cv2.waitKey(0)
cv2.destroyAllWindows()
引导滤波
import numpy as np
import cv2main_path="D:/Handletiling/NG_org_20230602103406819.bmp"def guideFilter(I, p, winSize, eps):mean_I = cv2.blur(I, winSize) mean_p = cv2.blur(p, winSize) mean_II = cv2.blur(I * I, winSize) mean_Ip = cv2.blur(I * p, winSize) var_I = mean_II - mean_I * mean_I cov_Ip = mean_Ip - mean_I * mean_p a = cov_Ip / (var_I + eps) b = mean_p - a * mean_I mean_a = cv2.blur(a, winSize) mean_b = cv2.blur(b, winSize) q = mean_a * I + mean_breturn qif __name__ == '__main__':eps = 0.01winSize = (5,5)image = cv2.imread(main_path, cv2.IMREAD_ANYCOLOR)image = cv2.resize(image, None,fx=0.7, fy=0.7, interpolation=cv2.INTER_CUBIC)I = image/255.0 #将图像归一化p =IguideFilter_img = guideFilter(I, p, winSize, eps)# 保存导向滤波结果guideFilter_img = guideFilter_img * 255guideFilter_img [guideFilter_img > 255] = 255guideFilter_img = np.round(guideFilter_img )guideFilter_img = guideFilter_img.astype(np.uint8)cv2.imshow("image",image)cv2.imshow("winSize_5", guideFilter_img )cv2.waitKey(0)cv2.destroyAllWindows()
求最大凸包
import cv2
import os
import numpy as np
from skimage.measure import labelmain_path="D:\Handletiling\luoya/NG/NG_org_20230602103407364.bmp"##method1 --opencv
def get_lagrest_connect_component1(img):# rgb->grayimg_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# gaussian filterimg_gray = cv2.GaussianBlur(img_gray, (5, 5), 0)# binary exp-threshold=0_, img_gray = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY_INV) # ret==threshold# find contourcontours, _ = cv2.findContours(img_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# cv2.drawContours(img_gray, contours, -1, 255, 3)# find the area_max regionarea = []for i in range(len(contours)):area.append(cv2.contourArea(contours[i]))if len(area) >= 1:max_idx = np.argmax(area)max_contour_area = area[max_idx]for k in range(len(contours)):if k != max_idx:cv2.fillPoly(img_gray, [contours[k]], 0)else:max_contour_area = 0return max_contour_area, img_grayif __name__ == '__main__':img = cv2.imread(main_path)max_area, img_gray = get_lagrest_connect_component1(img)print(max_area)cv2.imwrite('img_gray.jpg', img_gray)
判断曲直
1.查找轮廓,提取凸包
2.获得点集
3.计算导数方差
4.比较阈值
def calccurl(str,thresh):img = cv2.imread(str)# cv2.imshow('src',img)#提取凸包max_area, img_gray =get_lagrest_connect_component1(img)gray = img_gray#阈值处理ret,binary = cv2.threshold(gray,127,255,0)#查找轮廓,提取凸包contours,hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)hull = cv2.convexHull(contours[0])cv2.polylines(img_gray,[hull],True,(255,255,0),2)min_x=min(hull[:,0,0])max_x=max(hull[:,0,0])topList=[]bottomList=[]thresh_left=220thresh_right=30count=hull.shape[0]isthesame=Falsefor i in range(hull.shape[0]):point = tuple(hull[i][0]) # # cv2.circle(img, point, 1, (0, 255, 0) , 12)if point[0]<(max_x-thresh_right) and point[0]>(min_x+thresh_left):length=binary.shape[0]x1 = np.linspace(start=0, stop=length-1, num=length)temp=x1 * (binary[:, point[0]] / 255)n = np.sum(temp > 0)index=temp.sum()/(n*1.)# if i in[0,count-1]:# if not isthesame:# isthesame=True# else:# continueif point[1]>index:bottomList.append(point)# cv2.putText(img, str(i), point, cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)# print(str(i) + ":", point)else:topList.append(point)# cv2.putText(img, str(i), point, cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)# print(str(i) + ":", point)space = np.linspace(start=min_x+thresh_left, stop=max_x-thresh_right, num=15)space= np.ceil(space)length = img_gray.shape[0]x1 = np.linspace(start=0, stop=length - 1, num=length)tempM = (img_gray / 255.)* x1[:,None]if len(topList) >len(bottomList):topList.clear()for x in space:temp=tempM[:, int(x)]temp = temp[temp != 0]topList.append([x,temp.min()])# cv2.circle(img, (int(x),int(temp.min())), 1, (0, 255, 0), 12)# cv2.putText(img, str(x), (int(x),int(temp.min())), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)line = np.array(topList, dtype=float)else:bottomList.clear()for x in space:temp = tempM[:, int(x)]temp = temp[temp != 0]bottomList.append([x, temp.max()])# cv2.circle(img, (int(x), int(temp.max())), 1, (0, 255, 0), 12)# cv2.putText(img, str(x), (int(x),int(temp.max())), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)line = np.array(bottomList, dtype=float)if line.size > 0:#method1slopend=(line[-1,1]-line[0,1])/(line[-1,0]-line[0,0])slop=(line[1:,1]-line[:-1,1])/((line[1:,0]-line[:-1,0])+0.0001)dis=slop-slopendstd = np.std(dis)if std>thresh:return 0,stdreturn 1,0# method2# std= np.std(slop)if __name__ == '__main__':filesPath = os.listdir(main_path)threshstd=0.025files = tqdm(filesPath)for file in files:absolute_file_path = os.path.join(main_path, file)if '.bmp' in absolute_file_path.lower():result,std=calccurl(absolute_file_path,threshstd)if result:print(absolute_file_path+":", std)
结果
--------------------
std: 0.037498851806574245
全部代码
import cv2
import numpy as npimport os
from tqdm import tqdm
import shutil#需要检测弯曲的图片的文件夹地址
main_path="D:\Handletiling\src"def get_lagrest_connect_component1(img):img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img_gray = cv2.GaussianBlur(img_gray, (5, 5), 0)_, img_gray = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY_INV) # ret==thresholdcontours, _ = cv2.findContours(img_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)area = []for i in range(len(contours)):area.append(cv2.contourArea(contours[i]))if len(area) >= 1:max_idx = np.argmax(area)max_contour_area = area[max_idx]for k in range(len(contours)):if k != max_idx:cv2.fillPoly(img_gray, [contours[k]], 0)else:max_contour_area = 0return max_contour_area, img_graydef calccurl(str,thresh):img = cv2.imread(str)#提取凸包max_area, img_gray =get_lagrest_connect_component1(img)gray = img_gray#阈值处理ret,binary = cv2.threshold(gray,127,255,0)#查找轮廓contours,hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)hull = cv2.convexHull(contours[0])cv2.polylines(img_gray,[hull],True,(255,255,0),2)min_x=min(hull[:,0,0])max_x=max(hull[:,0,0])topList=[]bottomList=[]thresh_left=220thresh_right=30count=hull.shape[0]isthesame=Falsefor i in range(hull.shape[0]):point = tuple(hull[i][0]) ## cv2.circle(img, point, 1, (0, 255, 0) , 12)if point[0]<(max_x-thresh_right) and point[0]>(min_x+thresh_left):length=binary.shape[0]x1 = np.linspace(start=0, stop=length-1, num=length)temp=x1 * (binary[:, point[0]] / 255)n = np.sum(temp > 0)index=temp.sum()/(n*1.)# if i in[0,count-1]:# if not isthesame:# isthesame=True# else:# continueif point[1]>index:bottomList.append(point)# cv2.putText(img, str(i), point, cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)# print(str(i) + ":", point)else:topList.append(point)# cv2.putText(img, str(i), point, cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)# print(str(i) + ":", point)space = np.linspace(start=min_x+thresh_left, stop=max_x-thresh_right, num=15)space= np.ceil(space)length = img_gray.shape[0]x1 = np.linspace(start=0, stop=length - 1, num=length)tempM = (img_gray / 255.)* x1[:,None]if len(topList) >len(bottomList):topList.clear()for x in space:temp=tempM[:, int(x)]temp = temp[temp != 0]topList.append([x,temp.min()])# cv2.circle(img, (int(x),int(temp.min())), 1, (0, 255, 0), 12)# cv2.putText(img, str(x), (int(x),int(temp.min())), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)line = np.array(topList, dtype=float)else:bottomList.clear()for x in space:temp = tempM[:, int(x)]temp = temp[temp != 0]bottomList.append([x, temp.max()])# cv2.circle(img, (int(x), int(temp.max())), 1, (0, 255, 0), 12)# cv2.putText(img, str(x), (int(x),int(temp.max())), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)line = np.array(bottomList, dtype=float)if line.size > 0:#method1slopend=(line[-1,1]-line[0,1])/(line[-1,0]-line[0,0])slop=(line[1:,1]-line[:-1,1])/((line[1:,0]-line[:-1,0])+0.0001)dis=slop-slopendstd = np.std(dis)if std>thresh:return 0,stdreturn 1,0# method2# std= np.std(slop)if __name__ == '__main__':filesPath = os.listdir(main_path)threshstd=0.025files = tqdm(filesPath)for file in files:absolute_file_path = os.path.join(main_path, file)if '.bmp' in absolute_file_path.lower():result,std=calccurl(absolute_file_path,threshstd)if not result:print(absolute_file_path+"-图片弯曲:", std)
#结果
[00:00<00:01, 44.18it/s]D:\Handletiling\src\NG_org_20230602103409544.bmp-图片弯曲: 0.0334415572613885
[00:00<00:01, 44.24it/s]D:\Handletiling\src\NG_org_20230602103410530.bmp-图片弯曲: 0.037498851806574245