图像的分割之基于边缘的分割

边缘检测

import cv2 as cv
import numpy as np

# 边缘检测
img = cv.imread("./image.jpg", cv.IMREAD_GRAYSCALE)
# 梯度算子
# 标准定义形式
# g(x, y) ≈ |∂f(x, y)/∂x|+|∂f(x, y)/∂y|,其中原函数为f(x, y),处理后的函数为g(x, y)
# ∂f(x, y)/∂x = f(x, y+1)-f(x, y) ∂f(x, y)/∂y = f(x, y)-f(x+1, y)
# 另一种表现形式
# G = |Gx*I| + |Gy*I|
# 即使用内核Gx和Gy分别对图像I进行卷积,再进行相加,得到图像G
# roberts算子
# 内核Gx=[[1, 0], [0, -1]] Gy=[[0, 1], [-1, 0]]
kernelx = np.array([[1, 0], [0, -1]])
kernely = np.array([[0, 1], [-1, 0]])
robertsx = cv.filter2D(img, -1, kernelx)
robertsx = cv.convertScaleAbs(robertsx)
robertsy = cv.filter2D(img, -1, kernely)
robertsy = cv.convertScaleAbs(robertsy)
roberts = cv.addWeighted(robertsx, 0.5, robertsy, 0.5, 0)
# prewitt算子
#
kernelx = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]])
kernely = np.array([[-1, -1, -1], [0, 0, 0], [0, 0, 0]])
prewittx = cv.filter2D(img, -1, kernelx)
prewittx = cv.convertScaleAbs(prewittx)
prewitty = cv.filter2D(img, -1, kernely)
prewittx = cv.convertScaleAbs(prewittx)
prewitt = cv.addWeighted(robertsx, 0.5, robertsy, 0.5, 0)
# sobel算子
# 正确的用法,若原函数为f(x, y),处理后的函数为g(x, y),
# 则这里相当于g(x, y) = |∂f(x, y)/∂x|+|∂f(x, y)/∂y|
# 注意第二个参数ddepth表示存储图像每个像素的位数,
# 确定彩色图像的每个像素可能有的颜色数,或者确定灰度图像的每个像素可能有的灰度级数.
# ddepth=-1表示输出与原图像一样的图像深度
sobelx = cv.Sobel(img, -1, 1, 0)
sobelx = cv.convertScaleAbs(sobelx)
sobely = cv.Sobel(img, -1, 0, 1)
sobely = cv.convertScaleAbs(sobely)
sobel1 = cv.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
# 错误的用法,若原函数为f(x, y),处理后的函数为g(x, y),
# 则这里相当于g(x, y) = ∂²f(x, y)/∂x∂y,显然不符合梯度算子的定义
sobel2 = cv.Sobel(img, -1, 1, 1)
# scharr算子
# 类似于sobel算子,只是使用的内核不同
# sobel算子使用的内核
# Gx = [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
# Gy = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]]
# scharr算子使用的内核
# Gx = [[-3, 0, 3], [-10, 0, 10], [-3, 0, 3]]
# Gy = [[-3, -10, -3], [0, 0, 0], [3, 10, 3]]
scharrx = cv.Sobel(img, -1, 1, 0, ksize=cv.FILTER_SCHARR)
scharrx = cv.convertScaleAbs(scharrx)
scharry = cv.Sobel(img, -1, 1, 0, ksize=cv.FILTER_SCHARR)
scharry = cv.convertScaleAbs(scharry)
scharr = cv.addWeighted(scharrx, 0.5, scharry, 0.5, 0)
# laplacian算子
# 内核
# Gx = [[0, -1, 0], [-1, 4, -1], [0, -1, 0]]
# Gy = [[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]
img_laplacian = cv.Laplacian(img, -1)
# kirsch算子
# 定义的8个内核
kernel1 = np.array([[5, 5, 5], [-3, 0, -3], [-3, -3, -3]])
kernel2 = np.array([[-3, 5, 5], [-3, 0, 5], [-3, -3, -3]])
kernel3 = np.array([[-3, -3, 5], [-3, 0, 5], [-3, -3, 5]])
kernel4 = np.array([[-3, -3, -3], [-3, 0, 5], [-3, 5, 5]])
kernel5 = np.array([[-3, -3, -3], [-3, 0, -3], [5, 5, 5]])
kernel6 = np.array([[-3, -3, -3], [5, 0, -3], [5, 5, -3]])
kernel7 = np.array([[5, -3, -3], [5, 0, -3], [5, -3, -3]])
kernel8 = np.array([[5, 5, -3], [5, 0, -3], [-3, -3, -3]])
# 用8个内核分别与原图像进行卷积
kirsch1 = cv.filter2D(img, -1, kernel1)
kirsch2 = cv.filter2D(img, -1, kernel2)
kirsch3 = cv.filter2D(img, -1, kernel3)
kirsch4 = cv.filter2D(img, -1, kernel4)
kirsch5 = cv.filter2D(img, -1, kernel5)
kirsch6 = cv.filter2D(img, -1, kernel6)
kirsch7 = cv.filter2D(img, -1, kernel7)
kirsch8 = cv.filter2D(img, -1, kernel8)
rows, cols = img.shape
kirsch = np.zeros((rows, cols), np.uint8)
for i in range(rows):
    for j in range(cols):
        # 找出每幅图像的不同像素中最大的值
        kirsch[i, j] = max(kirsch1[i, j], kirsch2[i, j], kirsch3[i, j], kirsch4[i, j],
                           kirsch5[i, j], kirsch6[i, j], kirsch7[i, j], kirsch8[i, j])
# LOG算子
# 先用高斯滤波对图像进行平滑,再用laplacian算子对图像进行边缘检测
# canny算子
canny = cv.Canny(img, 100, 200)
上一篇:结构光相机标定-3D Scanning Software源码编译


下一篇:5个常见的交叉验证技术介绍和可视化