image-processing - 편집기 - vb net listview imagelist




이미지를 이미지 컬렉션과 일치 (4)

많은 카드 이미지 모음과 특정 카드의 사진이 하나 있습니다. 어떤 컬렉션 이미지가 내 이미지와 가장 유사한 지 찾기 위해 어떤 도구를 사용할 수 있습니까?

수집 샘플은 다음과 같습니다.

내가 찾으려고하는 것은 다음과 같습니다.


내가 당신을 올바르게 이해한다면 당신은 사진으로 비교해야합니다. 여기에는 매우 간단하지만 효과적인 해결책이 있습니다 Sikuli 라고 Sikuli .

어떤 컬렉션 이미지가 내 이미지와 가장 유사한 지 찾기 위해 어떤 도구를 사용할 수 있습니까?

이 도구는 이미지 처리에 매우 효과적이며 카드 (이미지)가 이미 패턴으로 정의한 것과 유사한 지 확인할 수있을뿐만 아니라 부분 이미지 컨텐츠 ( 사각형 )도 검색 할 수 있습니다.

기본적으로 Python을 통해 기능을 확장 할 수 있습니다. 모든 ImageObject는 유사성 패턴을 백분율로 허용하도록 설정할 수 있으며 그렇게하면 원하는 것을 정확하게 찾을 수 있습니다.

이 도구의 또 다른 큰 장점은 하루에 기본을 배울 수 있다는 것입니다.

도움이 되었기를 바랍니다.


또한 다음과 같이 카드와 각 이미지의 표준화 된 상호 상관을 시도했습니다.

#!/bin/bash
size="300x400!"
convert card.png -colorspace RGB -normalize -resize $size card.jpg
for i in *.jpg
do 
   cc=$(convert $i -colorspace RGB -normalize -resize $size JPG:- | \
   compare - card.jpg -metric NCC null: 2>&1)
   echo "$cc:$i"
done | sort -n

그리고이 출력을 얻었습니다 (일치 품질로 정렬).

0.453999:abundance.jpg
0.550696:aggressive.jpg
0.629794:demystify.jpg

이는 카드가 demystify.jpg 와 가장 관련이 있음을 보여줍니다.

모든 이미지의 크기를 동일한 크기로 조정하고 대비를 표준화하여 쉽게 비교할 수 있고 대비 차이로 인한 효과가 최소화됩니다. 더 작게 만들면 상관 관계에 필요한 시간도 줄어 듭니다.


이미지 데이터를 벡터로 배열하고 컬렉션 이미지 벡터와 검색된 이미지 벡터 사이에서 내부 제품을 가져 와서 이것을 시도했습니다. 가장 유사한 벡터는 최고의 내적을 제공합니다. 동일한 길이의 벡터를 얻기 위해 모든 이미지의 크기를 같은 크기로 조정하여 내부 제품을 사용할 수 있습니다. 이 크기 조정은 제품 내부 계산 비용을 추가로 줄이고 실제 이미지의 대략적인 근사치를 제공합니다.

Matlab 또는 Octave로이를 빠르게 확인할 수 있습니다. 아래는 Matlab / Octave 스크립트입니다. 거기에 의견을 추가했습니다. 1에서 8까지의 변수 mult 를 변경하려고 시도했지만 (정수 값을 시도 할 수 있음) 모든 경우에 이미지 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 표준)를 취하는 다른 접근법을 시도해 보았으며 테스트 카드 이미지 의이 here 에서 찾은 많은 참조 이미지 모음 (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

척도 = 0.8;

demystify.jpg : 8572.84, sylvan_basilisk.jpg : 9440.18, steel_golem.jpg : 9445.36

척도 = 0.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


새로운 방법!

더 많은 이미지를 보았을 때 다음 ImageMagick 명령 또는 변형이 카드 상단의 문구를 추출하는 것으로 보입니다.

convert aggressiveurge.jpg -crop 80%x10%+10%+10% crop.png

이미지의 상단 10 %와 너비의 80 %를 차지합니다 (왼쪽 상단에서 10 %에서 시작하여 다음과 같이 crop.png 저장합니다).

그리고 다음과 같이 tessseract OCR을 통해 실행하십시오.

tesseract crop.png agg

다음을 포함하는 agg.txt 라는 파일을 얻습니다.

E‘ Aggressive Urge \L® E

grep 을 통해 정리하여 서로 인접한 대문자와 소문자 만 찾을 수 있습니다.

grep -Eo "\<[A-Za-z]+\>" agg.txt

얻을

Aggressive Urge

:-)





cbir