python Blob检测圆点

blob只能检测里面是黑色外面是白色的斑点

如果要检测里面是白色外面是黑色的斑点,则图像要取反

img_inv = 255 - img

原图

python Blob检测圆点_第1张图片

 

检测结果图

plt

python Blob检测圆点_第2张图片

 opencv

python Blob检测圆点_第3张图片

 

# 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)

你可能感兴趣的:(机器视觉与图形图像,大数据)