python图像分割

孤立点的检测

一阶导数通常会产生粗边缘。二阶导数对精细细节(细线、孤立点、噪声)有更强的响应。

所以,检测孤立点应该以二阶导数为基础,而二阶导数的差分计算为

这个差分计算可以通过一个 系数和为零 的kernel去完成

如果滤波器的响应超过一个规定的阈值,那我们就认为在kernel的中心找到了一个点。将找到的点记作1,其他的点看作0,于是就得到了一副二值图像

 

import numpy as np
import cv2


def point_detect(img):
    canvas = np.zeros(img.shape, dtype=np.uint8)  # 拷贝图像
    kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])  # 定义卷积核
    laplacian = cv2.filter2D(img, cv2.CV_16S, kernel)  # 拉普拉斯变换

    img_lap = cv2.convertScaleAbs(laplacian)  # 拉普拉斯图像
    # cv2.imshow('laplacian', img_lap)

    """
    孤立点是那些灰度差超过某个阈值T,被认为是孤立点的像素点
    """
    T = 0.9 * np.abs(laplacian).max()  # 阈值 T

    for i in range(img.shape[0]):  # 遍历图像,寻找孤立点
        for j in range(img.shape[1]):
            if (laplacian[i, j] > T) or (laplacian[i, j] < -T):  # 绝对值大于阈值的点
                canvas[i, j] = 255  # 二值处理
                cv2.circle(canvas, (j, i), 10, 255)  # 绘制圆

    return canvas


img = cv2.imread('img1.png', 0)


for i in range(20):      # 添加2000个胡椒噪声
    x = np.random.randint(0,img.shape[0])
    y = np.random.randint(0,img.shape[1])
    img[x][y] = 0  # 0 为pepper 噪声 255 为salt 噪声

ret = point_detect(img)
cv2.imshow('img', np.hstack((img, ret)))
cv2.imwrite('./image.png',np.hstack((img,ret)))
cv2.waitKey()
cv2.destroyAllWindows()

 python图像分割_第1张图片

线检测

复杂度更高的是线检测

由于二阶导数有更强的滤波器响应,并且比一阶导数有更细的线。但是二阶导数对噪声点会格外敏感,并且会产生双边缘响应

python图像分割_第2张图片

import numpy as np
import cv2

img = cv2.imread('./img1.png', 0)
kernel1 = np.array([[-1, -1, -1], [2, 2, 2], [-1, -1, -1]])  # 水平
kernel2 = np.array([[2, -1, -1], [-1, 2, -1], [-1, -1, 2]])  # +45
kernel3 = np.array([[-1, 2, -1], [-1, 2, -1], [-1, 2, -1]])  # 垂直
kernel4 = np.array([[-1, -1, 2], [-1, 2, -1], [2, -1, -1]])  # -45

dst1 = cv2.filter2D(img, cv2.CV_16S, kernel1)  # 水平检测
dst1 = cv2.convertScaleAbs(dst1)

dst2 = cv2.filter2D(img, cv2.CV_16S, kernel2)  # 45 检测
dst2 = cv2.normalize(dst2, None, 0, 255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
dst = dst2.copy()  # 拷贝归一化后的图像
dst[dst2 <= 254] = 0

dst3 = cv2.filter2D(img, cv2.CV_16S, kernel3)  # 垂直检测
dst3 = cv2.convertScaleAbs(dst3)

dst4 = cv2.filter2D(img, cv2.CV_16S, kernel4)  # -45 检测
dst4 = cv2.convertScaleAbs(dst4)

cv2.imshow('img', np.hstack((img, dst2, dst)))
cv2.waitKey()
cv2.destroyAllWindows()

Canny边缘检测

import numpy as np
import cv2

img = cv2.imread('./img1.png', 0)
"""
Canny 是基于一阶微分的
首先用高斯滤波平滑图像。
计算梯度幅值图像和方向角度图像
对梯度图像应用非极大值抑制(根据第二步求出的角度图像,用该像素点 比较 在梯度方向和其反方向的像素点。如果该像素点的梯度幅值最大则保留;否则,删去。)
使用双阈值处理和连通性分析来检测连接边缘  (根据设置的两个阈值( 为低阈值  为高阈值),就会将幅值图像划为三部分,进行如下的分割
像素点的响应强度是 > TH 的,那么认为是真正的边缘
像素点的响应强度是 < TL的,那么认为是伪边缘,删去
如果介于两者之间,则检查周围的8领域,如果存在真正的边缘就保留,为了连接边缘。否则就删去)
"""
dst = cv2.Canny(img, 100, 200)  # Canny 边缘检测

cv2.imshow("img", np.hstack((img, dst)))
cv2.imwrite('./image.png',np.hstack((img,dst)))
cv2.waitKey()
cv2.destroyAllWindows()

python图像分割_第3张图片 

Hough变换直线检测

import numpy as np
import cv2

img = cv2.imread('./img2.png', 0)  # 读取图像
img = cv2.GaussianBlur(img, (7, 7), sigmaX=1)  # 高斯模糊图像

img_bin = cv2.Canny(img, 50, 100)  # 得到二值图像

lines = cv2.HoughLinesP(img_bin, 1, np.pi / 180, threshold=10)  # Hough 变换
for line in lines:
    x1, y1, x2, y2 = line[0]  # 提取线段
    cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 1)  # 在原图上绘制线段

cv2.imshow('Canny', img_bin)  # 显示 Canny 检测的图像
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()

Hough变换圆环检测

Hough 变换除了能用来检测直线外,也能用来检测圆环

import cv2
import numpy as np

img = cv2.imread('./img2.png', 1)
img_blur = cv2.GaussianBlur(img, (7, 7), sigmaX=1)  # 高斯模糊
img_gray = cv2.cvtColor(img_blur, cv2.COLOR_BGR2GRAY)  # 灰度化

circles = cv2.HoughCircles(img_gray, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=50, minRadius=50,
                           maxRadius=100)  # Hough圆环检测
circles = np.uint(np.around(circles))  # 将数组元素四舍五入成整数

for i in circles[0]:  # 遍历圆环
    x, y, r = i  # 取出圆横坐标、纵坐标、半径
    cv2.circle(img, (x, y), r, (0, 0, 255), 2)  # 绘制圆
    cv2.circle(img, (x, y), 1, (0, 0, 255), 3)  # 绘制圆心

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

你可能感兴趣的:(opencv,人工智能)