Сравнение двух изображений через хэш C++

У нас есть два одинаковых изображений, переведённых в градацию серого. Нам нужно сравнить эти изображения, и если они одинаковы, то мы делаем что-то.

Перерыл более нескольких сотен сайтов, но решения устарели, либо же не удаётся реализовать.

Тем временем есть готовые функции для расчёта хэша в OpenCv, но, в документации файл есть, а на деле его нет (я имею ввиду img_hash), что делает данный способ решения проблемы невозможным.


Ответы (1 шт):

Автор решения: Georgy Firsov

С OpenCV не подскажу, но может такой способ подойдёт тоже.

Общая идея: помещаем файл аккурат в память и от этого массива байт считаем контрольную сумму:

#include <Windows.h>
#include <atlbase.h>

constexpr auto szFilePath = LR"(C:\Folder\img1.png)"

...

ATL::CHandle hFile;
hFile.m_h = ::CreateFile(
   szFilePath,
   GENERIC_READ,
   FILE_SHARE_READ,
   nullptr,
   OPEN_EXISTING,
   0,
   nullptr
);

if (hFile == INVALID_HANDLE_VALUE) // Ошибка

ATL::CHandle hFileMapping;
hFileMapping.m_h = ::CreateFileMapping(
   hFile,
   nullptr,
   PAGE_READONLY,
   0,
   0, 
   nullptr
);

if (!hFileMapping) // ошибка (тут именно на ноль проверка)

const BYTE* pData = (const BYTE*)::MapViewOfFile(
   hFileMapping,
   FILE_MAP_READ,
   0, 0, 0
);

if (!pData) // ошибка

//
// В массиве данных pData лежат данные png 
// файла в бинарном виде
//

// По завершении работы надо файл размапить
::UnmapViewOfFile(pData);

Далее надо узнать размер файла. Это вот так делается:

LARGE_INTEGER liFileSize = { 0 };
BOOL bResult = ::GetFileSizeEx(hFile, &liFileSize);

if (!bResult) // ошибка

LONGLONG dwFileSize = liFileSize.QuadPart; // Это и есть размер файла

Ну а дальше, зная размер массива данных и указатель на него, можно легко посчитать хэш от этого массива. Например, с помощью RtlComputeCrc32 из NtDll.dll.

→ Ссылка