【画像登録】Cannyエッジ検出+テンプレート登録赤外線・可視光デュアルチャンネルデータ

研究目的

最近、UAV リモートセンシングの赤外線と可視光のデュアルチャンネルデータ登録を行っていますが、赤外線カメラの視野が狭いため、登録の目的は主に赤外線画像内の該当部分を切り出すことです。可視光を維持しながら可視光の視野を確保し、高い解像度はそのままに。

この記事のアイデア

この記事では、Canny エッジ検出を使用して赤外線および可視光のエッジ特徴を抽出し、テンプレート マッチングを使用して位置合わせを実行することを試みます。赤外線画像と可視光画像の解像度は同じではないため、赤外線画像の解像度に近づけるには可視光を継続的にダウンサンプリングする必要があります。

一般に、クロスモーダルレジストレーションに従来の方法を使用すると、主に赤外線画像の特徴の数が少ないため、効果が限定されますが、十分な照明と明らかな建築上の特徴がある場合には、一定の効果があります。学習は将来使用される予定です。プロジェクトの都合上、メソッドと関連画像は公開されていません。コードはここにアーカイブされています。

実験コード

import numpy as np
import argparse
import cv2
import os

if __name__ == '__main__':
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--image", required=False, default=r"lr/Infrared.jpg", help="红外图像路径")
    ap.add_argument("-v", "--visualize", required=False, default=r"rgb/Zoom.jpg", help="可见光图像路径")
    ap.add_argument("-o", "--output", required=False, default=r"output", help="输出文件夹路径")
    args = vars(ap.parse_args())

    # 读取红外图像/灰度化/边缘检测
    template = cv2.imread(args["image"])
    template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
    template = cv2.Canny(template, 50, 200)
    (tH, tW) = template.shape[:2]

    # 读取可见光图像
    image = cv2.imread(args["visualize"])
    # image = cv2.resize(image, (tW, tH))
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    found = None

    for scale in np.linspace(0.2, 1.0, 20)[::-1]:
        # 多尺度缩小可见光图像
        resized = cv2.resize(gray, (int(gray.shape[1] * scale), int(gray.shape[0] * scale)))
        r = gray.shape[1] / float(resized.shape[1])

        # 若缩小的尺度小于红外图像尺寸,跳出循环
        if resized.shape[0] < tH or resized.shape[1] < tW:
            break

        # 对缩小之后的图像进行边缘检测
        edged = cv2.Canny(resized, 50, 200)
        '''
        cv2.matchTemplate  模板匹配
        :param 检测图像 模板 模板匹配方法
        :returns 相似度结果矩阵:(宽: image.shape[1]-template.shape[1]+1; 高:image.shape[0]-template.shape[0]+1)
        '''
        result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF)
        # print("edged_shape:{}".format(edged.shape))  # (3888, 5184)
        # print("template_shape:{}".format(template.shape))  # (512, 640)
        # print("result_shape:{}".format(result.shape))  # (3377, 4545)

        # 查找模板中最大相似度值和位置
        _, maxVal, _, maxLoc = cv2.minMaxLoc(result)

        # 可选:查看匹配图范围
        # clone = np.dstack([edged, edged, edged])
        # clone = edged
        # cv2.rectangle(clone, (maxLoc[0], maxLoc[1]), (maxLoc[0] + tW, maxLoc[1] + tH), (0, 0, 255), 2)
        # cv2.imwrite(os.path.join(args["output"], "Visualize", "visualize.jpg"), clone)

        # 若在裁剪区域找到相似度更高的匹配点,更新found
        if found is None or maxVal > found[0]:
            found = (maxVal, maxLoc, r)

    # 得到匹配度最高的矩阵框坐标
    _, maxLoc, r = found
    (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r))
    (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r))

    # cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2)
    crop_img = image[startY:endY, startX:endX]
    # cv2.imshow("Image", image)
    # cv2.imshow("Crop Image", crop_img)
    # cv2.waitKey(0)


    thermal_image = cv2.imread(args["image"], cv2.IMREAD_COLOR)
    # cropping out the matched part of the thermal image
    crop_img = cv2.resize(crop_img, (thermal_image.shape[1], thermal_image.shape[0]))

    # 创建输出文件夹存储裁剪后的可见光影像
    if not os.path.exists(os.path.join(args["output"], "process")):
        os.mkdir(os.path.join(args["output"], "process"))
    # 保存图片
    cv2.imwrite(os.path.join(args["output"], "process", os.path.basename(args["visualize"])), crop_img)

    # 创建对比图像
    final = np.concatenate((crop_img, thermal_image), axis=1)
    if not os.path.exists(os.path.join(args["output"], "results")):
        os.mkdir(os.path.join(args["output"], "results"))
    cv2.imwrite(os.path.join(args["output"], "results", os.path.basename(args["visualize"])), final)

おすすめ

転載: blog.csdn.net/qq1198768105/article/details/134022797