孤立点检测
在Python中使用OpenCV进行孤立点(异常点)检测,可以通过应用统计分析或者使用OpenCV的findContours和convexHull函数来识别。以下是一个简单的例子,使用OpenCV的findContours和convexHull来识别并绘制孤立点。
孤立点的检测,是检测嵌在一幅图像的恒定区域或亮度几乎不变的区域里的孤立点。孤立点的检测以二阶导数为基础。
当孤立点在卷积模板的中心时,拉普拉斯滤波器的响应很强烈,而孤立点在非模板中心时,拉普拉斯滤波器响应为零。当滤波器在一个点的响应超过设定阈值 T,则认为在卷积核的中心检测到了孤立点,标记为 1,而其它点都被标记为 0,从而产生一副二值图像。
注意:
-
(1)本节所称的孤立点检测,是绝对意义上的孤立点,即一个孤立的像素。人眼所能感知、识别的孤立点,通常来说其实是一个微小的区域,而不是孤立的一个像素,因此并不能用这种方法检测。
-
(2)使用 Laplace 算子进行图像孤立点检测,推荐使用 scipy.signal 实现卷积运算,不建议使用 cv2.filter2D 实现。后者自动将卷积结果进行归一化处理,不便于通过阈值 T 检测孤立点。
# 11.1 图像孤立点检测 (Laplace 算子)imgGray = cv2.imread("../images/Fig1004.tif", flags=0)hImg, wImg = imgGray.shape# scipy.signal 实现卷积运算 (注意:不能用 cv2.filter2D 处理)from scipy import signalkernelLaplace = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]]) # Laplacian kernelimgLaplace = signal.convolve2d(imgGray, kernelLaplace, boundary='symm', mode='same') # same 卷积# 在原图上用半径为 5 的圆圈标记角点T = 0.9 * max(imgLaplace.max(), -imgLaplace.min())imgPoint = np.zeros((hImg, wImg), np.uint8) # 创建黑色图像for h in range(hImg):for w in range(wImg):if (imgLaplace[h, w] > T) or (imgLaplace[h, w] < -T):imgPoint[h, w] = 255 # 二值处理cv2.circle(imgPoint, (w, h), 10, 255)print(imgLaplace.shape, imgLaplace.max(), imgLaplace.min(), T)plt.figure(figsize=(9, 6))plt.subplot(131), plt.axis('off'), plt.title("Original")plt.imshow(imgGray, cmap='gray', vmin=0, vmax=255)plt.subplot(132), plt.axis('off'), plt.title("Laplacian K2")plt.imshow(imgLaplace, cmap='gray', vmin=0, vmax=255)plt.subplot(133), plt.axis('off'), plt.title("Isolated point")plt.imshow(imgPoint, cmap='gray', vmin=0, vmax=255)plt.tight_layout()plt.show()
import cv2
import numpy as np# 读取图像
image = cv2.imread('isolated_points.png', 0)# 二值化图像
_, thresh = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)# 寻找轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 遍历轮廓并计算凸包
for contour in contours:# 计算凸包hull = cv2.convexHull(contour)# 如果凸包的点数小于等于3,则可能是孤立点if len(hull) <= 3:# 绘制原始轮廓cv2.drawContours(image, [contour], -1, (0, 255, 0), 2)# 显示图像
cv2.imshow('Isolated Points', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
在这个例子中,我们首先读取了一个包含孤立点的图像,然后将其转换为二值图像。接着,我们使用findContours函数找到所有轮廓。对于每个轮廓,我们计算其凸包,并检查凸包的点数。如果点数小于等于3,则可能是孤立点,我们将其用绿色线条绘制在原图上。最后,我们显示处理后的图像
C++
使用拉普拉斯核进行点的检测
#include<iostream>
#include<opencv2/opencv.hpp>using namespace cv;
using namespace std;int main()
{Mat image, image_gray, image_bw, image_bw2; image = imread("lena孤立点.png"); //读取图像;if (image.empty()){cout << "读取错误" << endl;return -1;}//转换为灰度图像cvtColor(image, image_gray, COLOR_BGR2GRAY);cv::imshow("image_gray", image_gray);//1.构建拉普拉斯孤立点检测卷积核Mat Laplacian_kernel = (cv::Mat_<float>(3, 3) << 0, 1, 0,1, -4, 1,0, 1, 0);//2.卷积运算filter2D(image_gray, image_bw, -1, Laplacian_kernel);cv::imshow("image_bw", image_bw);//3.阈值处理threshold(image_bw, image_bw2, 250, 255, 0); //通过0,1调节二值图像背景颜色cv::imshow("image_bw2", image_bw2);cv::waitKey(0); //暂停,保持图像显示,等待按键结束return 0;
}