整体等于其部分之和
整体大于其部分之和
这里采用了拉普拉斯算子来进行边缘检测
Laplace算子作为边缘检测的方法之一,也是工程数学中常用的一种积分变换。把图像的像素值想象成一个变化的曲线。对应变化的曲线,一阶导数的极值位置,二阶导数为0,利用这个来检测边缘
实现的边缘检测效果如下所示
对应的代码为:
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
def laplace_filter(image):
kernel_size = 3
height, width = image.shape
padding_size = int((kernel_size - 1) / 2)
template = np.array([[1, 1, 1],
[1, -8, 1],
[1, 1, 1]])
padded_img = np.pad(image, padding_size, 'constant')
edge_of_img = np.zeros_like(image, dtype=float)
for i in range(height):
for j in range(width):
corr = padded_img[i:i + kernel_size, j:j + kernel_size]
edge_of_img[i, j] = np.abs(np.sum(template * corr))
return edge_of_img
def process():
src = np.array(Image.open("man.jpg").convert("L"))
edge = laplace_filter(src)
plt.subplot(1, 2, 1)
plt.imshow(src, cmap='gray')
plt.axis("off")
plt.subplot(1, 2, 2)
plt.imshow(edge, cmap='gray')
plt.axis("off")
plt.show()
if __name__ == '__main__':
process()
这里采用的是全局阈值的方法进行分割
全局阈值的计算过程为
全局阈值分割图像的实现效果如下所示
实现的代码如下所示:
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import cv2
def global_threshold(image):
error = 1
old_t = 127
new_t = 0
while True:
m1 = image[image <= old_t]
m2 = image[image > old_t]
mean1 = np.mean(m1)
mean2 = np.mean(m2)
new_t = (mean1 + mean2) / 2
if (np.abs(new_t - old_t)) <= error:
break
else:
old_t = new_t
return new_t
def process():
src = np.array(Image.open("man.jpg").convert("L"))
line = global_threshold(src)
ret, dst = cv2.threshold(src, line, 255, cv2.THRESH_BINARY)
plt.subplot(1, 2, 1)
plt.imshow(src, cmap='gray')
plt.axis("off")
plt.subplot(1, 2, 2)
plt.imshow(dst, cmap='gray')
plt.axis("off")
plt.show()
if __name__ == '__main__':
process()
相对于上述方法来说,otus是一种找出全局最佳阈值的方法
大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。
它被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小
其实现的效果如下所示
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import cv2
def otsu(image): # 传入的参数为ndarray形式
height, width = image.shape
pixels = np.zeros(256)
for i in range(height):
for j in range(width):
pixels[int(image[i][j])] += 1
var_best = 0.0
current_best = 0
for k in range(1, 256):
front = pixels[:k].sum() / (height * width)
back = pixels[k:].sum() / (height * width)
front_mean = 0.0
back_mean = 0.0
for i in range(k):
front_mean += i * pixels[i]
for j in range(k, 256):
back_mean += j * pixels[j]
front_mean = front_mean / pixels[:k].sum()
back_mean = back_mean / pixels[k:].sum()
gray_sum = front_mean * front + back_mean * back
tmp_var = front * np.power((gray_sum - front_mean), 2) + back * np.power((gray_sum - back_mean), 2)
if tmp_var > var_best:
current_best = k
var_best = tmp_var
return current_best
def process():
src = np.array(Image.open("man.jpg").convert("L"))
best = otsu(src)
print(best)
ret, dst = cv2.threshold(src, best, 255, cv2.THRESH_BINARY)
plt.subplot(1, 2, 1)
plt.imshow(src, cmap='gray')
plt.axis("off")
plt.subplot(1, 2, 2)
plt.imshow(dst, cmap='gray')
plt.axis("off")
plt.show()
if __name__ == '__main__':
process()