图像匹配SATD

发布时间:2023年12月28日

一、SATD是什么

提示:这里可以添加技术名词解释

SATD(Sum of Absolute Transformed Differences)是一种用于图像匹配的算法,其原理主要包含以下步骤:

  1. 将模板图像与待匹配图像做差,得到一个差值矩阵Q。
  2. 对差值矩阵Q进行Hadamard变换(一种特殊的矩阵变换)。Hadamard变换等价于把原图像Q矩阵左右分别乘以一个Hadamard变换矩阵H。Hadamard变换矩阵H的元素都是1或-1,是一个正交矩阵,可以由MATLAB中的hadamard(n)函数生成,n代表n阶方阵。
  3. 对变换后的矩阵求其元素的绝对值之和,得到一个SATD值。这个SATD值作为相似度的判别依据。
  4. 对所有待匹配的子图都进行如上的变换后,找到SATD值最小的子图,便是最佳匹配。

以上信息仅供参考,如需更多信息,建议查阅图像处理相关的书籍或咨询图像处理专家。

二、 技术细节

1.matlab 连续读取图片,并截取区域

为了连续读取1到1000张图片,并截取中间的100*100区域,然后重新存储为M1到M1000,你可以使用以下的MATLAB代码:

% 设定图片文件夹路径
folderPath = 'path_to_your_image_folder'; % 请替换为你的图片文件夹路径

% 遍历每张图片
for i = 1:1000
    % 生成当前图片的文件名
    fileName = fullfile(folderPath, sprintf('I%d.jpg', i)); % 假设原始图片命名为I1.jpg, I2.jpg, ... I1000.jpg
    
    % 读取图片
    img = imread(fileName);
    
    % 检查图片是否读取成功
    if isempty(img)
        error(sprintf('无法读取图片: %s', fileName));
    end
    
    % 计算截取区域
    [height, width, ~] = size(img);
    xStart = max(1, width/2 - 50);    % 100*100区域的左起点
    yStart = max(1, height/2 - 50);   % 100*100区域的上起点
    cropImg = img(yStart:yStart+99, xStart:xStart+99, :);
    
    % 存储截取后的图片
    outputFileName = fullfile(folderPath, sprintf('M%d.jpg', i));
    imwrite(cropImg, outputFileName);
end

注意事项:

  1. 请确保你的图片是.jpg格式。如果不是,请在代码中修改对应的扩展名。
  2. 这个代码假设原始图片的命名是连续的,从I1.jpgI1000.jpg。如果实际命名与此不符,请相应地调整文件名生成部分。
  3. 这个代码会截取图片中心附近的100*100区域。如果原始图片的尺寸小于这个区域,代码会自动调整截取区域以确保不会超出图片边界。

2.matlab SATD相似度识别

close all
clear all
clc
% src=double(rgb2gray(imread('baby.jpg'))); %长宽相等的
% mask=double(rgb2gray(imread('模板图像_bdd.jpg'))); %长宽相等的

src=double(rgb2gray(imread('frame_1442.jpg'))); %长宽相等的
mask=double(rgb2gray(imread('frame_1442_mask.jpg'))); %长宽相等的

[M,K]=size(src); %搜索图大小
N=size(mask,1); %模板大小
%%
hdm_matrix=hadamard(N); %hadamard变换矩阵
hdm=zeros(M-N+1,K-N+1); %保存SATD值
for i=1:M-N+1
    for j=1:K-N+1
        temp=(src(i:i+N-1,j:j+N-1)-mask)/256;
        sw=(hdm_matrix*temp*hdm_matrix)/256;
        hdm(i,j)=sum(sum(abs(sw)));
    end
end
min_hdm=min(min(hdm));
[x, y]=find(hdm==min_hdm);
figure, imshow(uint8(mask));
title('模板图像');
imwrite(uint8(mask),'模板图像_zhuti_gray.jpg');
figure, imshow(uint8(src)); 
hold on;
rectangle('position',[y,x,N-1,N-1],'edgecolor','r');
title('STAD匹配结果'); 
hold off;

3.matlab 在多维矩阵中找最小值

在MATLAB中,min(min(hdm)) 的作用是从一个多维数组(比如矩阵)中找到最小值。

具体解释如下:

  1. min(hdm):当 hdm 是一个矩阵时,这个操作会返回每一列的最小值,结果是一个行向量。
  2. min( ... ):外面的 min 函数作用于之前得到的行向量,返回该行向量中的最小值。

所以,min_hdm = min(min(hdm)); 的意思是找到 hdm 矩阵中的最小值,并将其赋值给 min_hdm

例如,如果 hdm 是以下矩阵:

hdm = [3, 7, 2;
       8, 1, 6;
       4, 5, 9];

那么 min(hdm) 会返回 [3, 1, 2](每列的最小值),然后 min(min(hdm)) 会返回 1,这是整个矩阵的最小值。

这段MATLAB代码是在寻找数组hdm中与最小值min_hdm相等的元素的索引。

具体解释如下:

  1. hdm == min_hdm:这部分会返回一个逻辑数组,其中值为true的位置表示hdm中与min_hdm相等的元素。
  2. find(...):这个函数会返回逻辑数组中true的位置的索引。所以,如果hdm == min_hdm返回的是一个与hdm相同大小的逻辑数组,那么find(...)会返回所有与min_hdm相等的元素的索引。
  3. [x, y] = ...:这部分将返回两个向量。向量x包含所有与min_hdm相等的元素的行索引,而向量y包含它们的列索引。

例如,如果:

hdm = [3, 7, 2;
       8, 1, 6;
       4, 5, 9];
min_hdm = 1;

那么 [x, y] = find(hdm == min_hdm) 将返回 x = [2], y = [2],表示在第二行第二列的位置上,hdm的值是1。

三、c++ 实现SATD

3.1 OpenCV和C++实现SATD

下面是使用OpenCV和C++实现SATD(Sum of Absolute Transformed Differences)的一个简单示例。在这个例子中,我将假设你已经有了待匹配的模板图像(template_img)和待匹配的源图像(source_img)。

注意:这个代码只是一个基本的示例,可能需要根据你的具体需求进行修改和优化。

#include <opencv2/opencv.hpp>
#include <iostream>

// 计算SATD
double computeSATD(const cv::Mat &img1, const cv::Mat &img2) {
    cv::Mat diff;
    cv::absdiff(img1, img2, diff); // 计算绝对差值
    cv::Mat gray;
    cv::cvtColor(diff, gray, cv::COLOR_BGR2GRAY); // 转换为灰度图像
    cv::Mat abs_diff_mat;
    cv::convertScaleAbs(gray, abs_diff_mat); // 转换为绝对值
    double sum = cv::sum(abs_diff_mat)[0]; // 计算总和
    return sum;
}

int main() {
    // 读取图像
    cv::Mat template_img = cv::imread("template.png", cv::IMREAD_GRAYSCALE);
    cv::Mat source_img = cv::imread("source.png", cv::IMREAD_GRAYSCALE);
    if (template_img.empty() || source_img.empty()) {
        std::cout << "无法加载图像" << std::endl;
        return -1;
    }

    // 确保图像大小相同
    if (template_img.size() != source_img.size()) {
        std::cout << "图像大小不一致" << std::endl;
        return -1;
    }

    // 计算SATD值
    double satd = computeSATD(template_img, source_img);
    std::cout << "SATD值: " << satd << std::endl;

    return 0;
}

这个代码首先计算两个图像的绝对差值,然后将差值图像转换为灰度图像,再将其转换为绝对值。最后,它计算并返回所有像素的绝对值之和,这就是SATD值。注意,这个代码没有进行任何形式的模板匹配优化,例如使用滑动窗口或快速近似算法。对于大型图像或实时应用,你可能需要使用这些优化方法来提高性能。

3.2 c++ opencv

要使用C++和OpenCV实现SATD(Sum of Absolute Transformed Differences)图像匹配,你需要遵循以下步骤:

  1. 设置环境

    • 安装OpenCV库。你可以从OpenCV官网下载并按照说明进行安装。
    • 创建一个C++项目,并配置OpenCV库。
  2. 读取图像

    • 使用OpenCV的imread函数读取模板图像和待匹配图像。
  3. 预处理

    • 如果需要,对图像进行预处理,如灰度化、平滑等。
  4. 定义SATD函数

    • 编写一个函数来计算两个图像的SATD值。该函数将接收两个图像作为输入,并返回它们的SATD值。
  5. 滑动窗口匹配

    • 在待匹配图像上使用滑动窗口技术。对于每个窗口位置,计算模板图像与当前窗口的SATD值。
    • 记录每个位置的SATD值。
  6. 找到最佳匹配

    • 找到SATD值最小的位置,这就是最佳匹配位置。
  7. 显示结果

    • 在待匹配图像上标出最佳匹配位置。
    • 使用OpenCV的imshow函数显示结果图像。
  8. 保存/输出结果

    • 如果需要,保存匹配结果图像或输出相关信息。
  9. 代码示例
    下面是一个简化的C++和OpenCV实现SATD图像匹配的代码示例:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <cmath>

double computeSATD(const cv::Mat& templateImg, const cv::Mat& sourceRegion) {
    cv::Mat absDiff;
    cv::absdiff(templateImg, sourceRegion, absDiff); // 计算绝对差值
    return cv::sum(absDiff)[0]; // 返回绝对值之和
}

cv::Point findMatch(const cv::Mat& templateImg, const cv::Mat& sourceImg) {
    int minSATD = INT_MAX;
    cv::Point bestLocation;
    int templateHeight = templateImg.rows;
    int templateWidth = templateImg.cols;
    for (int i = 0; i < sourceImg.rows - templateHeight; ++i) {
        for (int j = 0; j < sourceImg.cols - templateWidth; ++j) {
            cv::Rect region(j, i, templateWidth, templateHeight);
            double currentSATD = computeSATD(templateImg, sourceImg(region));
            if (currentSATD < minSATD) {
                minSATD = currentSATD;
                bestLocation = cv::Point(j, i); // 更新最佳匹配位置
            }
        }
    }
    return bestLocation; // 返回最佳匹配位置
}

int main() {
    cv::Mat templateImg = cv::imread("template.png", cv::IMREAD_GRAYSCALE); // 读取模板图像(灰度)
    cv::Mat sourceImg = cv::imread("source.png", cv::IMREAD_GRAYSCALE); // 读取待匹配图像(灰度)
    if (templateImg.empty() || sourceImg.empty()) {
        std::cerr << "Error: Could not load images." << std::endl;
        return -1;
    }
    cv::Point matchLocation = findMatch(templateImg, sourceImg); // 找到最佳匹配位置
    // 在源图像上画出匹配位置(例如使用矩形)并显示结果...
    return 0;
}

这个示例展示了如何使用C++和OpenCV来实现基本的SATD图像匹配。注意,对于实际应用,可能需要进一步的优化和调整以提高性能和准确性。

小结

提示:这里可以添加总结

例如:

提供先进的推理,复杂的指令,更多的创造力。

文章来源:https://blog.csdn.net/ganhui13000/article/details/135233585
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。