遥感图像匹配(高分4匹配Landsat8)-Python+Opencv/SIFT+GDAL

高分系列遥感影像的一个问题是难以进行精准的几何校正,通常是在专业软件(如ENVI)中处理,需要借助标准影像手动选择地面控制点来进行校正,操作比较复杂。本文的思路是借助Landsat8影像来进行关键点匹配,这样就能自动得到控制点。难点有:
①两种不同卫星的影像分辨率和细节方面差异较大,难以进行准确的匹配。为解决此问题,将分辨率较高的Landsat影像进行了均值滤波。
②遥感影像的存储格式不能直接用opencv处理,需要转换成8位整型灰度图,这里只用了一个全色波段。

# -*- coding: utf-8 -*-
# @File  : siftMatch.py
# @Author: Freezinghot
# @Date  : 2021/2/7
# @Desc  : SIFT图像配准
import cv2
import numpy as np
import gdal
from PIL import Image
from matplotlib import pyplot as plt


# SIFT特征检测
def sift_kp(image):
    #gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)    # 灰度图转换,如果是普通RGB图像需要这一行
    sift = cv2.xfeatures2d.SIFT_create()                    # 实例化sift
    kp, des = sift.detectAndCompute(image, None)            # 找出关键点并计算关键点对应的sift特征向量。
# kp 是一个关键点列表。des是一个numpy数组,其大小是关键的数目乘以128.image表示输入的灰度图
# kp_image = cv2.drawKeypoints(gray_image, kp, None)      # 在图中画出关键点(输入,关键点,输出)
    kp_image = cv2.drawKeypoints(image, kp, None)
    # print(kp, des)
    return kp_image, kp, des


def get_good_match(des1, des2):
    bf = cv2.BFMatcher()
    matches = bf.knnMatch(des1, des2, k=2)  # des1为模板图,des2为匹配图
    #matches = sorted(matches, key=lambda x: x[0].distance / x[1].distance)
    good = []
    for m, n in matches:
        if m.distance < 0.75 * n.distance:
            good.append(m)
    return good


def siftImageAlignment(img1, img2):
    _, kp1, des1 = sift_kp(img1)
    _, kp2, des2 = sift_kp(img2)
    goodMatch = get_good_match(des1, des2)
    if len(goodMatch) > 10:
        ptsA = np.float32([kp1[m.queryIdx].pt for m in goodMatch]).reshape(-1, 1, 2)
        ptsB = np.float32([kp2[m.trainIdx].pt for m in goodMatch]).reshape(-1, 1, 2)
        ransacReprojThreshold = 5
        H, status = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, ransacReprojThreshold)
        imgOut = cv2.warpPerspective(img2, H, (img1.shape[1], img1.shape[0]),
                                     flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
    else:
        print("goodMatches less than 10")

    return imgOut, H, status


def tiftoint8(min, max, imdata):
    scale = max-min
    out_img = ((imdata/scale)*256).astype(np.uint8)
    return out_img

inds2 = "E:\\RSDATA\\GFdata\\LC08_L1TP_120035_20200424_01_T1\\LC08_L1TP_120035_20200424_20200508_01_T1_B8_resized50.TIF"
inds1 = "E:\\RSDATA\\GFdata\\tempout\\GF4_PMI_E121.6_N37.1_20200424_L1A0000296007\\GF4_PMS_E121.6_N37.1_20200424_L1A0000296007_clip.tiff"
img1 = gdal.Open(inds1)	
img2 = gdal.Open(inds2)
im1_width = img1.RasterXSize  # 栅格矩阵的列数
im1_height = img1.RasterYSize  # 栅格矩阵的行数
im1_bands = img1.RasterCount  # 波段数
im1_geotrans = img1.GetGeoTransform() # 获取仿射矩阵信息
im1_proj = img1.GetProjection()   # 获取投影信息
im2_width = img2.RasterXSize  # 栅格矩阵的列数
im2_height = img2.RasterYSize  # 栅格矩阵的行数
im2_bands = img2.RasterCount  # 波段数

im_data1 = img1.ReadAsArray(0,0,im1_width,im1_height)#获取数据
max1 = im_data1.max()
min1 = im_data1.min()
in_img1uint8 = tiftoint8(min1, max1, im_data1)
im_data2 = img2.ReadAsArray(0,0,im2_width,im2_height)#获取数据
max2 = im_data2.max()
min2 = im_data2.min()
in_img2uint8 = tiftoint8(min2, max2, im_data2)
'''
# 平滑滤波
in_img1uint8 = cv2.blur(in_img1uint8[4],(3,5))#模板大小3*5
in_img2uint8 = cv2.blur(in_img2uint8,(3,5))
plt.subplot(1,2,1),plt.imshow(in_img1uint8,'gray')
plt.subplot(1,2,2),plt.imshow(in_img2uint8,'gray')
plt.show()
'''
in_img2uint8 = cv2.blur(in_img2uint8,(3,5))
# 执行sift
_, kp1, des1 = sift_kp(in_img1uint8[0])
_, kp2, des2 = sift_kp(in_img2uint8)
goodMatch = get_good_match(des1, des2)
print(goodMatch)
# 提取关键点中的坐标
src_pts = np.float32([kp1[m.queryIdx].pt for m in goodMatch]).reshape(-1,1,2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in goodMatch]).reshape(-1,1,2)
print(src_pts,dst_pts)
#H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 2.0)
#wrapimg = cv2.warpPerspective(in_img1uint8[0], H, (im1_width, im1_height))
wrapimg, H, status = siftImageAlignment(in_img1uint8[0], in_img2uint8)
# 显示匹配点和匹配结果
matchesMask = status.ravel().tolist()
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
        singlePointColor = None,
        matchesMask = matchesMask, # draw only inliers
        flags = 2)
img3 = cv2.drawMatches(in_img1uint8[0],kp1,in_img2uint8,kp2,goodMatch,None,**draw_params)
plt.imshow(img3,'gray')
plt.show()
# 写入新的tiff文件
datatype = gdal.GDT_UInt16
wrapimg = ((wrapimg*32767)//255).astype(np.uint16)
path = "E:\\RSDATA\\GFdata\\tempout\\LC8wrapimg.tif"
driver = gdal.GetDriverByName("GTiff")
dataset = driver.Create(path, im1_width, im1_height, 1, datatype,options=["INTERLEAVE=BAND"])
print("创建文件成功")
dataset.SetGeoTransform(im1_geotrans)  # 写入仿射变换参数
dataset.SetProjection(im1_proj)  # 写入投影
print("写入投影")
dataset.GetRasterBand(1).WriteArray(wrapimg)
del dataset

匹配结果图

本来是计划用匹配点生成的转换矩阵直接对高分影像做一个变换,结果不理想,后面考虑将提取到的匹配点作为控制点,用gdal对原影像进行控制点校正。程序不完善,只是一个预研实验,在这里做个记录,供大家参考。

  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
本程序主要对遥感图像实现三种处理:几何校正、图像增强和图像配准。这三种处理都可以独立实现,然而对于原始的遥感图像将这三种处理依次进行效果更佳。 具体操作步骤如下: 1.在主窗口打开图像1 2.选择【几何校正】菜单,打开【图像几何校正】对话框进行几何校正。在此对话框中,首先打开待校正图像2,然后点击【选取特正点】按钮,按照提示依次在待校正图像和基准图像中手动选取特征点,最后点击【校正图像】得到几何校正结果,如果达到预期效果,则点击【保存并在主窗口打开】按钮,保存此校正图片,并在主窗口打开。 3.选择【图像增强】菜单,打开【图像增强】对话框进行图像增强。在此对话框中,首先在相应的处理类别(如:直方图增强、灰度增强等)中选择具体方法(如:均衡化、规定化等),然后点击本类别的按钮。增强后的结果会在右侧显示,如果达到预期效果,则点击【保存并在主窗口打开】按钮,保存此增强后的图片,并在主窗口打开。 4.选择【图像配准】菜单,打开【图像配准】对话框进行图像配准。在此对话框中,首先打开待匹配图像3,然后选择“半自动”或“手动”方法并点击【选取特正点】按钮,按照提示依次在待配准图像和基准图像中半自动或手动选取特征点(如果在半自动选取中特征点对应错误,可以更改特征点),最后点击【匹配图像】得到图像配准结果,如果达到预期效果,则点击【保存并在主窗口打开】按钮,保存此校正图片,并在主窗口打开。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值