1.角点检测方法
遥感图像角点检测是一种用于识别图像中角点(也称为兴趣点)的方法,角点通常代表着图像中的显著特征点。以下是一些常用的遥感图像角点检测方法:
-
Harris 角点检测算法:Harris 算法通过计算图像中每个像素的灰度变化量,并结合局部邻域的自相关矩阵,来判断该点是否为角点。
-
Shi-Tomasi 角点检测算法:Shi-Tomasi 算法是对 Harris 算法的改进,它选取图像中最显著的角点,通过设置角点响应函数的阈值。
-
FAST(Features from Accelerated Segment Test)角点检测算法:FAST 角点检测算法是一种基于像素强度的高速角点检测方法,通过利用圆周上像素的灰度变化快速确定角点。
-
SIFT(Scale-Invariant Feature Transform)角点检测算法:SIFT 是一种局部特征描述符,其中包含了角点检测步骤,它可以在不同尺度和旋转下对角点进行检测。
-
SURF(Speeded-Up Robust Features)角点检测算法:SURF 是一种快速且具有尺度不变性的图像特征描述符,其中包含了用于角点检测的步骤。
-
ORB(Oriented FAST and Rotated BRIEF)角点检测算法:ORB 是一种基于 FAST 角点检测器和 BRIEF 描述符的算法,用于检测和描述图像中的角点。
-
MinEigen (角点检测器):全称为 "Minimum Eigenvalue" 角点检测器。
MinEigen 角点检测器是一种基于像素灰度值的方法,它使用了图像中的 Hessian 矩阵来检测角点。Hessian 矩阵描述了图像的局部结构信息,而最小特征值代表了灰度变化最明显的方向。MinEigen 角点检测器的工作原理如下:(1)对于图像中的每个像素点,构建一个局部窗口(通常是一个固定大小的正方形或圆)。(2)在窗口内计算 Hessian 矩阵。(3)计算 Hessian 矩阵的特征值,其中最小特征值表示该像素点的角点响应强度。(4)根据设定的阈值或其他规则来确定是否将该点标识为角点。(5)MinEigen 角点检测器相对于一些其他方法具有较好的响应速度,在计算上较为高效。它在许多计算机视觉应用中被广泛使用,如目标跟踪、图像拼接和三维重建等。
-
BRISK算法是2011年ICCV上《BRISK:Binary Robust Invariant Scalable Keypoints》文章中,提出来的一种特征提取算法,也是一种二进制的特征描述算子。它具有较好的旋转不变性、尺度不变性,较好的鲁棒性。在图像配准应用中,速度比较:SIFT>SURF>BRISK>FREAK>ORB,在对有较大模糊的图像配准时,BRISK算法在其中表现最为出色。
这些方法在遥感图像处理中常被广泛应用,可以用于目标检测、图像匹配、图像拼接等任务。根据实际需求和图像特征,选择适合的角点检测方法进行处理。不同的角点检测方法有各自的优缺点和适用条件,在实际应用中需要根据具体情况进行选择和调整参数
2.python实现代码及效果展示
2.1 Harris角点检测
代码函数:
get_img_Harris(inputimgfile,k=0.04,window_size=3,IsAllBands=True,band_num=1)
参数:k=0.04,window_size = 3,IsAllBands=False,band_num=1
IsAllBands=False,只计算band_num波段
IsAllBands=True,计算所有波段。
from osgeo import gdal
import numpy as np
from scipy.ndimage import convolve
#定义角点计算函
def get_Harris(image,k,window_size):
# 运行 Harris 角点检测算法
# 计算图像的梯度
dx = np.gradient(image, axis=1)
dy = np.gradient(image, axis=0)
# 计算角点响应函数
Ix2 = dx ** 2
Iy2 = dy ** 2
Ixy = dx * dy
Sx2 = convolve(Ix2, np.ones((window_size, window_size)))
Sy2 = convolve(Iy2, np.ones((window_size, window_size)))
Sxy = convolve(Ixy, np.ones((window_size, window_size)))
det = Sx2 * Sy2 - Sxy ** 2
trace = Sx2 + Sy2
response = det - k * trace ** 2
# 阈值化角点响应函数
threshold = 0.01 * np.max(response)
corner_map = np.zeros_like(image)
corner_map[response > threshold] = 255
return corner_map
#k是角点响应参数
def get_img_Harris(inputimgfile,k=0.04,window_size = 3,IsAllBands=False,band_num=1):
gdal.UseExceptions()
# 读取影像数据
dataset = gdal.Open(inputimgfile)
band_nums=dataset.RasterCount #波段数
cols = dataset.RasterXSize
rows = dataset.RasterYSize
if IsAllBands==False: #只计算指定第band_num波段的结果
band = dataset.GetRasterBand(band_num)
# 将波段数据加载到一个 NumPy 数组中
image = band.ReadAsArray()
corner_map = get_Harris(image, k, window_size)
# 将结果保存为影像文件
driver = gdal.GetDriverByName('GTiff')
outimgfile = inputimgfile.replace('.tif', '_Harris_Band'+str(band_num)+'.img')
output_dataset = driver.Create(outimgfile, cols, rows, 1, gdal.GDT_Byte)
output_dataset.GetRasterBand(1).WriteArray(corner_map)
# 设置投影和地理转换信息
output_dataset.SetProjection(dataset.GetProjection())
output_dataset.SetGeoTransform(dataset.GetGeoTransform())
output_dataset.FlushCache()
# 关闭数据集
output_dataset = None
dataset = None
print("计算Harris角点已保存为:" + outimgfile)
else: #计算所有波段的Harris角点
# 将结果保存为影像文件
driver = gdal.GetDriverByName('GTiff')
outimgfile = inputimgfile.replace('.tif', '_HarrisAllBands.img')
output_dataset = driver.Create(outimgfile, cols, rows, band_nums, gdal.GDT_Byte)
for i in range(1,band_nums+1):
band = dataset.GetRasterBand(i)
# 将波段数据加载到一个 NumPy 数组中
image = band.ReadAsArray()
corner_map = get_Harris(image, k, window_size)
output_dataset.GetRasterBand(i).WriteArray(corner_map)
# 设置投影和地理转换信息
output_dataset.SetProjection(dataset.GetProjection())
output_dataset.SetGeoTransform(dataset.GetGeoTransform())
output_dataset.FlushCache()
# 关闭数据集
output_dataset = None
dataset = None
print("计算Harris角点已保存为:" + outimgfile)
if __name__=='__main__':
inputimgfile=r'E:\2022桌面\lena_rs.tif'
get_img_Harris(inputimgfile,k=0.04,window_size=3,IsAllBands=True)
效果:所有波段和第一波段效果图
原图
所有波段计算结果
第一波段计算结果
2.2 Shi-Tomasi角点检测
和Harris方法类似
代码如下:
from osgeo import gdal
import numpy as np
from scipy.ndimage import convolve
#定义角点计算函
def get_Shi_Tomasi(image,window_size,threshold):
# 运行 Harris 角点检测算法
# 计算图像的梯度
dx = np.gradient(image, axis=1)
dy = np.gradient(image, axis=0)
# 计算角点响应函数(Shi-Tomasi)
Ix2 = dx ** 2
Iy2 = dy ** 2
Ixy = dx * dy
Sx2 = convolve(Ix2, np.ones((3, 3)))
Sy2 = convolve(Iy2, np.ones((3, 3)))
Sxy = convolve(Ixy, np.ones((3, 3)))
det = Sx2 * Sy2 - Sxy ** 2
trace = Sx2 + Sy2
# trace[trace < threshold] = threshold # threshold
trace[trace == 0] = np.finfo(float).eps # 防止除以零
response = np.minimum(det / trace, threshold)
# 阈值化角点响应函数
corner_map = np.zeros_like(image)
corner_map[response > threshold] = 255
return corner_map
#k是角点响应参数
def get_img_Shi_Tomasi(inputimgfile,window_size = 3,threshold=0.01,IsAllBands=False,band_num=1):
gdal.UseExceptions()
# 读取影像数据
dataset = gdal.Open(inputimgfile)
band_nums=dataset.RasterCount #波段数
cols = dataset.RasterXSize
rows = dataset.RasterYSize
if IsAllBands==False: #只计算指定第band_num波段的结果
band = dataset.GetRasterBand(band_num)
# 将波段数据加载到一个 NumPy 数组中
image = band.ReadAsArray()
corner_map = get_Shi_Tomasi(image,threshold, window_size)
# 将结果保存为影像文件
driver = gdal.GetDriverByName('GTiff')
outimgfile = inputimgfile.replace('.tif', '_Shi_Tomasi_Band'+str(band_num)+'.img')
output_dataset = driver.Create(outimgfile, cols, rows, 1, gdal.GDT_Byte)
output_dataset.GetRasterBand(1).WriteArray(corner_map)
# 设置投影和地理转换信息
output_dataset.SetProjection(dataset.GetProjection())
output_dataset.SetGeoTransform(dataset.GetGeoTransform())
output_dataset.FlushCache()
# 关闭数据集
output_dataset = None
dataset = None
print("计算Harris角点已保存为:" + outimgfile)
else: #计算所有波段的Harris角点
# 将结果保存为影像文件
driver = gdal.GetDriverByName('GTiff')
outimgfile = inputimgfile.replace('.tif', '_Shi_TomasiAllBands.img')
output_dataset = driver.Create(outimgfile, cols, rows, band_nums, gdal.GDT_Byte)
for i in range(1,band_nums+1):
band = dataset.GetRasterBand(i)
# 将波段数据加载到一个 NumPy 数组中
image = band.ReadAsArray()
corner_map = get_Shi_Tomasi(image,threshold, window_size)
output_dataset.GetRasterBand(i).WriteArray(corner_map)
# 设置投影和地理转换信息
output_dataset.SetProjection(dataset.GetProjection())
output_dataset.SetGeoTransform(dataset.GetGeoTransform())
output_dataset.FlushCache()
# 关闭数据集
output_dataset = None
dataset = None
print("计算Harris角点已保存为:" + outimgfile)
if __name__=='__main__':
inputimgfile=r'E:\2022桌面\lena_rs.tif'
get_img_Shi_Tomasi(inputimgfile,threshold=0.01,window_size=3,IsAllBands=False)
2.3 FAST角点检测
代码
"""
Edward Rosten和Tom Drummond在2006年发表的“Machine learning for high-speed corner detection”文章中提出了一种FAST特征,
并在2010年对这篇论文作了小幅度的修改后重新发表。FAST的全称为Features From Accelerated Segment Test。Rosten等人将FAST角点定义为:
若某像素点与其周围领域内足够多的像素点处于不同的区域,则该像素点可能为角点。也就是某些属性与众不同,考虑灰度图像,
即若该点的灰度值比其周围领域内足够多的像素点的灰度值大或者小,则该点可能为角点。
FAST算法比其他已知的角点检测算法要快很多倍,但是当图片中的噪点较多时,它的健壮性并不好,而且算法的效果还依赖于一个阈值tt。
而且FAST不产生多尺度特征而且FAST特征点没有方向信息,这样就会失去旋转不变性。
"""
from osgeo import gdal
import numpy as np
from skimage.feature import corner_fast
def get_img_FAST(inputimgfile,outimgfile,band_num=1):
gdal.UseExceptions()
# 读取影像数据
dataset = gdal.Open(inputimgfile)
band = dataset.GetRasterBand(band_num)
cols = dataset.RasterXSize
rows = dataset.RasterYSize
# 将波段数据加载到一个 NumPy 数组中
data = band.ReadAsArray(0, 0, cols, rows)
# 运行 FAST 角点检测算法
corners = corner_fast(data,12,threshold=0.025)
# 创建一个和原始影像相同尺寸的二值图像,将角点标记为白色
result = np.zeros((rows, cols), dtype=np.uint8)
# result[corners] = 255
corner_indices = np.transpose(np.nonzero(corners)) # 转换为整数索引
for idx in corner_indices:
result[idx[0], idx[1]] = 255
# 将结果保存为影像文件
driver = gdal.GetDriverByName('GTiff')
output_dataset = driver.Create(outimgfile, cols, rows, 1, gdal.GDT_Byte)
output_dataset.GetRasterBand(1).WriteArray(result)
# 设置投影和地理转换信息
output_dataset.SetProjection(dataset.GetProjection())
output_dataset.SetGeoTransform(dataset.GetGeoTransform())
output_dataset.FlushCache()
# 关闭数据集
output_dataset = None
dataset = None
print("计算FAST已保存为:" + outimgfile)
if __name__=='__main__':
inputimgfile=r'E:\2022桌面\lena_grey.jpg'
#检测图片格式
outimgfile = inputimgfile.replace('.jpg', '_3FAST.img')
get_img_FAST(inputimgfile, outimgfile,band_num=1)