我通过将图像数据排列为向量并获取集合图像向量和搜索到的图像向量之间的内积来尝试此方法。最相似的向量将给出最高的内积。我将所有图像的大小调整为相同的大小以获得相等长度的向量,这样我就可以取内积。这种调整大小将额外减少内积计算成本,并提供实际图像的粗略近似。
您可以使用 Matlab 或 Octave 快速检查这一点。下面是 Matlab/Octave 脚本。我在那里添加了 cmets。我尝试将变量 mult 从 1 更改为 8(您可以尝试任何整数值),对于所有这些情况,图像 Demystify 给出了卡片图像的最高内积。对于 mult = 8,我在 Matlab 中得到以下 ip 向量:
ip =
683007892
558305537
604013365
如您所见,它为图像 Demystify 提供了 683007892 的最高内积。
% load images
imCardPhoto = imread('0.png');
imDemystify = imread('1.jpg');
imAggressiveUrge = imread('2.jpg');
imAbundance = imread('3.jpg');
% you can experiment with the size by varying mult
mult = 8;
size = [17 12]*mult;
% resize with nearest neighbor interpolation
smallCardPhoto = imresize(imCardPhoto, size);
smallDemystify = imresize(imDemystify, size);
smallAggressiveUrge = imresize(imAggressiveUrge, size);
smallAbundance = imresize(imAbundance, size);
% image collection: each image is vectorized. if we have n images, this
% will be a (size_rows*size_columns*channels) x n matrix
collection = [double(smallDemystify(:)) ...
double(smallAggressiveUrge(:)) ...
double(smallAbundance(:))];
% vectorize searched image. this will be a (size_rows*size_columns*channels) x 1
% vector
x = double(smallCardPhoto(:));
% take the inner product of x and each image vector in collection. this
% will result in a n x 1 vector. the higher the inner product is, more similar the
% image and searched image(that is x)
ip = collection' * x;
编辑
我尝试了另一种方法,基本上采用参考图像和卡片图像之间的欧几里得距离(l2 范数),它给了我很好的结果,我在link 找到了大量参考图像(383 张图像)你的测试卡图片。
这里我没有获取整个图像,而是提取了包含图像的上部并用于比较。
在以下步骤中,所有训练图像和测试图像在进行任何处理之前调整为预定义大小。
- 从训练图像中提取图像区域
- 对这些图像执行形态闭合以获得粗略的近似值(此步骤可能不是必需的)
- 将这些图像矢量化并存储在一个训练集中(我称它为训练集,即使这种方法没有训练)
- 加载测试卡图像,提取图像感兴趣区域 (ROI),应用闭合,然后矢量化
- 计算每个参考图像向量与测试图像向量之间的欧式距离
- 选择最小距离项(或前k项)
我使用 OpenCV 在 C++ 中完成了这项工作。我还包括了一些使用不同尺度的测试结果。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <windows.h>
using namespace cv;
using namespace std;
#define INPUT_FOLDER_PATH string("Your test image folder path")
#define TRAIN_IMG_FOLDER_PATH string("Your training image folder path")
void search()
{
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
vector<Mat> images;
vector<string> labelNames;
int label = 0;
double scale = .2; // you can experiment with scale
Size imgSize(200*scale, 285*scale); // training sample images are all 200 x 285 (width x height)
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
// get all training samples in the directory
hFind = FindFirstFile((TRAIN_IMG_FOLDER_PATH + string("*")).c_str(), &ffd);
if (INVALID_HANDLE_VALUE == hFind)
{
cout << "INVALID_HANDLE_VALUE: " << GetLastError() << endl;
return;
}
do
{
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
Mat im = imread(TRAIN_IMG_FOLDER_PATH+string(ffd.cFileName));
Mat re;
resize(im, re, imgSize, 0, 0); // resize the image
// extract only the upper part that contains the image
Mat roi = re(Rect(re.cols*.1, re.rows*35/285.0, re.cols*.8, re.rows*125/285.0));
// get a coarse approximation
morphologyEx(roi, roi, MORPH_CLOSE, kernel);
images.push_back(roi.reshape(1)); // vectorize the roi
labelNames.push_back(string(ffd.cFileName));
}
}
while (FindNextFile(hFind, &ffd) != 0);
// load the test image, apply the same preprocessing done for training images
Mat test = imread(INPUT_FOLDER_PATH+string("0.png"));
Mat re;
resize(test, re, imgSize, 0, 0);
Mat roi = re(Rect(re.cols*.1, re.rows*35/285.0, re.cols*.8, re.rows*125/285.0));
morphologyEx(roi, roi, MORPH_CLOSE, kernel);
Mat testre = roi.reshape(1);
struct imgnorm2_t
{
string name;
double norm2;
};
vector<imgnorm2_t> imgnorm;
for (size_t i = 0; i < images.size(); i++)
{
imgnorm2_t data = {labelNames[i],
norm(images[i], testre) /* take the l2-norm (euclidean distance) */};
imgnorm.push_back(data); // store data
}
// sort stored data based on euclidean-distance in the ascending order
sort(imgnorm.begin(), imgnorm.end(),
[] (imgnorm2_t& first, imgnorm2_t& second) { return (first.norm2 < second.norm2); });
for (size_t i = 0; i < imgnorm.size(); i++)
{
cout << imgnorm[i].name << " : " << imgnorm[i].norm2 << endl;
}
}
结果:
比例 = 1.0;
demystify.jpg:10989.6,sylvan_basilisk.jpg:11990.7,scathe_zombies.jpg:12307.6
比例 = .8;
demystify.jpg : 8572.84, sylvan_basilisk.jpg : 9440.18, steel_golem.jpg : 9445.36
比例 = .6;
demystify.jpg:6226.6,steel_golem.jpg:6887.96,sylvan_basilisk.jpg:7013.05
比例 = .4;
demystify.jpg : 4185.68, steel_golem.jpg : 4544.64, sylvan_basilisk.jpg : 4699.67
比例 = .2;
demystify.jpg:1903.05,steel_golem.jpg:2154.64,sylvan_basilisk.jpg:2277.42