blob只能检测里面是黑色外面是白色的斑点
如果要检测里面是白色外面是黑色的斑点,则图像要取反
img_inv = 255 - img
原图
检测结果图
plt
opencv
# coding:utf-8
import math
import cv2
import numpy as np
import xml.etree.ElementTree as ET
import random
import matplotlib.pyplot as plt
def get_distance_point2line(point, line_ab): # 求点到直线的距离
"""
Args:
point: [x0, y0]
line_ab: [k, b]
"""
k, b = line_ab
distance = abs(k * point[0] - point[1] + b) / math.sqrt(k ** 2 + 1)
return distance
# 没有考虑垂直和水平线的情况
def drawLines(img, allCirclesCenter):
# 计算两排点的中心线
nptest = np.array(allCirclesCenter)
line = cv2.fitLine(nptest, cv2.DIST_L2, 0, 0.001, 0.0)
# print(line)
k = line[1] / line[0]
b = line[3] - k * line[2]
# 如果是水平线
if k <= 10e-5:
pass
# 如果是垂直
if k > 10e5:
pass
print('y = {:0.8f}x + {:0.8f}'.format(k[0], b[0]))
ptStart, ptEnd = (0, int(k * 0 + b)), (img.shape[1], int(k * img.shape[1] + b))
# 坐标点取得整数需要修改*************** 画一线占满整个图片的线
cv2.line(img, ptStart, ptEnd, (0, 0, 255), thickness=2, lineType=3)
# cv2.imshow("line", img)
# cv2.waitKey()
# 区分上下各点,拟合两条直线
line1_yx, line2_yx = [], []
for i in allCirclesCenter:
if i[1] < float(k * i[0] + b):
line1_yx.append(i)
else:
line2_yx.append(i)
# line1 求第一条直线
nptest1 = np.array(line1_yx)
line1 = cv2.fitLine(nptest1, cv2.DIST_L2, 0, 0.01, 0.0)
k1 = line1[1] / line1[0]
b1 = line1[3] - k1 * line1[2]
# print(line1)
print('line1')
print('y = {:0.8f}x + {:0.8f}'.format(k1[0], b1[0]))
for i in line1_yx: # 显示点到直线的距离
point = i
line_ = k1, b1
dis = get_distance_point2line(point, line_)
# print('距离: ' + str(dis))
ptStart, ptEnd = (0, int(k1 * 0 + b1)), (img.shape[1], int(k1 * img.shape[1] + b1))# 坐标点取得整数需要修改***************
cv2.line(img, ptStart, ptEnd, ( 255, 0, 0), 2)
# cv2.imshow("line1", img)
# lin2 求第二条直线
nptest2 = np.array(line2_yx)
line2 = cv2.fitLine(nptest2, cv2.DIST_L2, 0, 0.01, 0.0)
k2 = line2[1] / line2[0]
b2 = line2[3] - k2 * line2[2]
# print(line2)
print('line2')
print('y = {:0.8f}x + {:0.8f}'.format(k2[0], b2[0]))
ptStart, ptEnd = (0, int(k2 * 0 + b2)), (img.shape[1], int(k2 * img.shape[1] + b2)) # 坐标点取得整数需要修改***************
cv2.line(img, ptStart, ptEnd, ( 255, 0, 0), 2) # 像素值必须是整数****************
# cv2.imshow("line2", img)
# cv2.waitKey()
imgNormal = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(imgNormal)
plt.show()
def mainFigure(img):
paramsOut = cv2.SimpleBlobDetector_Params()
# Setup SimpleBlobDetector parameters.
# print('params')
# print(params)
# print(type(params))
# Filter by Area.
paramsOut.filterByArea = True
paramsOut.minArea = 5000
paramsOut.maxArea = 10e3
paramsOut.minDistBetweenBlobs = 25
paramsOut.filterByColor = True
paramsOut.filterByConvexity = False
paramsOut.minThreshold = 10
paramsOut.maxThreshold = 30*2.5
# tweak these as you see fit
# Filter by Circularity
# params.filterByCircularity = False
# params.minCircularity = 1
# params.blobColor = 0
# # # Filter by Convexity
# params.filterByConvexity = True
# params.minConvexity = 1
# Filter by Inertia
# params.filterByInertia = True
# params.filterByInertia = False
# params.minInertiaRatio = 0.1
gray_src= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Detect blobs.
# image = cv2.resize(gray_img, (int(img.shape[1]/4),int(img.shape[0]/4)), 1, 1, cv2.INTER_LINEAR)
# image = cv2.resize(gray_img, dsize=None, fx=0.25, fy=0.25, interpolation=cv2.INTER_LINEAR)
minThreshValue = 35
_, gray = cv2.threshold(gray_src, minThreshValue, 255, cv2.THRESH_BINARY)
gray = cv2.resize(gray, dsize=None, fx=1, fy=1, interpolation=cv2.INTER_LINEAR)
# cv2.imshow("gray1",gray)
kernel = np.ones((3, 3), dtype=np.uint8)
gray = cv2.dilate(gray, kernel, 1) # 1:迭代次数,也就是执行几次膨胀操作
gray = cv2.erode(gray, kernel, 1)
# plt.imshow(gray)
# cv2.imshow("gray",gray)
# 找到距离原点(0,0)最近和最远的点
# 检测外侧圆
detector = cv2.SimpleBlobDetector_create(paramsOut)
keypoints = detector.detect(gray)
# opencv
im_with_keypoints = cv2.drawKeypoints(gray, keypoints, np.array([]), (255, 0, 0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# im_with_keypoints = cv2.drawKeypoints(img, keypoints, np.array([]), (0, 255, 0), cv2.DRAW_MATCHES_FLAGS_DEFAULT)
# print(keypoints)
# cv2.imshow("zero_gray", gray)
# 检测内侧圆 图像取反
paramsIn = cv2.SimpleBlobDetector_Params()
paramsIn.filterByArea = True
paramsIn.minArea = 100
paramsIn.maxArea = 500
paramsIn.minDistBetweenBlobs = 10
paramsIn.filterByColor = True
paramsIn.filterByConvexity = False
paramsIn.minThreshold = 30
paramsIn.maxThreshold = 30*2.5
# 图像取反
needleGray = 255 - gray.copy()
cv2.imshow('needleGray', needleGray)
detector2 = cv2.SimpleBlobDetector_create(paramsIn)
needleKeypoints = detector2.detect(needleGray)
# opencv
needle_keypoints = cv2.drawKeypoints(needleGray, needleKeypoints, np.array([]), (255, 0, 0),
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
allNeedlePoints = []
if keypoints is not None:
for i in range(len(needleKeypoints)):
allNeedlePoints.append(needleKeypoints[i].pt)
# 不可能大多数是斜的,直接按照大多数的点集拟合即可
# print(allCirclesCenter)
# if allCirclesCenter is not None:
if len(allNeedlePoints) > 10:
drawLines(needle_keypoints, allNeedlePoints)
color_img = cv2.cvtColor(im_with_keypoints, cv2.COLOR_BGR2RGB)
needle_img = cv2.cvtColor(needle_keypoints, cv2.COLOR_BGR2RGB)
cv2.imshow('holeShow', color_img)
cv2.imshow('needleShow', needle_img)
cv2.waitKey()
if __name__ == "__main__":
# # # 单张图片测试
# img = cv2.imread("images/HenFeng/HF01.jpg",1)
# img = cv2.imread("images/Snap_0.jpg",1)
# img = cv2.imread("images/Holes/Hole2.jpg",1)
# mainFigure(img)
# # 所有图片测试
for i in range(5):
fileName = "Zhen" + str(i+1) + ".jpg"
# img = cv2.imread("circles/Snap_007.jpg",1)
img = cv2.imread("images/ZhenJiao/" + fileName,1)
print(fileName)
mainFigure(img)