powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Сравнение 2х картинок
15 сообщений из 15, страница 1 из 1
Сравнение 2х картинок
    #39784464
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
День добрый.
Как сравнить 2 JPG файла? Думал, что GetHashCode поможет мне, но метод выдает всегда разные значения для одного файла.
Нашел такой способ:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
public static List<bool> GetHash(Bitmap bmpSource)
{
    List<bool> lResult = new List<bool>();         
    //create new image with 16x16 pixel
    Bitmap bmpMin = new Bitmap(bmpSource, new Size(16, 16));
    for (int j = 0; j < bmpMin.Height; j++)
    {
        for (int i = 0; i < bmpMin.Width; i++)
        {
            //reduce colors to true / false                
            lResult.Add(bmpMin.GetPixel(i, j).GetBrightness() < 0.5f);
        }             
    }
    return lResult;
}
List<bool> iHash1 = GetHash(new Bitmap(@"C:\mykoala1.jpg"));
List<bool> iHash2 = GetHash(new Bitmap(@"C:\mykoala2.jpg"));

//determine the number of equal pixel (x of 256)
int equalElements = iHash1.Zip(iHash2, (i, j) => i == j).Count(eq => eq);


Но какое-то сомнительное занятие пробегать по всем пикселям, учитывая, что картинок тысячи и проверка проводится каждые 10 минут.
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784471
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для объектов ссылочного типа не переопределенный метод GetHashCode возвращает хеш-код основанный на адресе объекта в памяти,
то есть создав 2 одинаковый объекта ссылочного типа (class) у них будет разный хеш-код, потому, что каждый экземпляр хранится отдельно, но если две ссылки указывают на один объект, значение будут равны.
Переопределите метод GetHashCode.
А вообще для сравнения больших файлов лучше использовать не хеширование, а контрольную сумму типа CRC32 или другие подобные алгоритмы.
Если переопределяете метод GetHashCode переопределите сразу метод Equals().
Типа значения поддерживают хеширование из коробки, но базовый метод адски тормозной, по этому, лучше его тоже переопределять
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784475
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman MejtesДля объектов ссылочного типа не переопределенный метод GetHashCode возвращает хеш-код основанный на адресе объекта в памяти,
то есть создав 2 одинаковый объекта ссылочного типа (class) у них будет разный хеш-код, потому, что каждый экземпляр хранится отдельно, но если две ссылки указывают на один объект, значение будут равны.
Переопределите метод GetHashCode.
А вообще для сравнения больших файлов лучше использовать не хеширование, а контрольную сумму типа CRC32 или другие подобные алгоритмы.
Если переопределяете метод GetHashCode переопределите сразу метод Equals().
Типа значения поддерживают хеширование из коробки, но базовый метод адски тормозной, по этому, лучше его тоже переопределять
я затупил. По первой ссылке в гугле нашел метод GetHashCode и не стал читать его описание, подумал, что для одной картинки всегда будет один результат. Сейчас уже понимаю, что метод не подходит.
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784478
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784490
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_ПавКак сравнить 2 JPG файла?а почему не музыкальный файл?
Сравниваем образы, фото, силуэты, пиксели, компрессию?
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784510
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123Супер_ПавКак сравнить 2 JPG файла?а почему не музыкальный файл?
Сравниваем образы, фото, силуэты, пиксели, компрессию?
на самом деле не важно какой файл. Просто в моем случае это JPG. Но мне не важны детали, которые различают файлы, важна контрольная сумма
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784518
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Павважна контрольная суммаона строится по деталям.
Иначе размер файла сравнивайте.
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784733
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Супер_ПавНо мне не важны детали, которые различают файлы, важна контрольная сумма[/quot]
https://www.google.com/search?q=C# file hash
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784827
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
static void Main(string[] args)
{
    var rsaHash = System.Security.Cryptography.SHA256.Create();
    using (var fileStream = File.Open(@"C:\MyFile.jpg", FileMode.Open))
    {
        var hash = rsaHash.ComputeHash(fileStream);
        var str = string.Join("", hash.Select(p => p.ToString("x2")));
        Console.WriteLine(str);
        Console.ReadKey();
    }
}
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784845
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
контрольная сумма CRC32
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
using System.Security.Cryptography;
using System.IO;

public class Crc32 : HashAlgorithm
{
    public const uint DefaultPolynomial = 0xEDB88320;
    public const uint DefaultSeed = 0xffffffff;

    private uint _hash;

    private readonly uint _seed;
    private readonly uint[] _table;

    private static uint[] defaultTable;

    public Crc32()
    {
        _table = InitializeTable(DefaultPolynomial);
        _seed = DefaultSeed;
        Initialize();
    }

    public Crc32(uint polynomial, uint seed)
    {
        _table = InitializeTable(polynomial);
        _seed = seed;
        Initialize();
    }

    public override void Initialize()
    {
        _hash = _seed;
    }

    protected override void HashCore(byte[] buffer, int start, int length)
    {
        _hash = CalculateHash(_table, _hash, buffer, start, length);
    }

    protected override byte[] HashFinal()
    {
        byte[] hashBuffer = UInt32ToBigEndianBytes(~_hash);
        HashValue = hashBuffer;
        return hashBuffer;
    }

    public override int HashSize
    {
        get { return 32; }
    }

    /// <summary> Рассчитывает контрольную сумму </summary>
    /// <param name="buffer">Буфер данных</param>
    /// <returns>Контрольная сумма</returns>
    public static uint Compute(byte[] buffer)
    {
        return ~CalculateHash(InitializeTable(DefaultPolynomial), DefaultSeed, buffer, 0, buffer.Length);
    }

    /// <summary> Рассчитывает контрольную сумму </summary>
    /// <param name="seed">Начальное значение</param>
    /// <param name="buffer">Буфер данных</param>
    /// <returns>Контрольная сумма</returns>
    public static uint Compute(uint seed, byte[] buffer)
    {
        return ~CalculateHash(InitializeTable(DefaultPolynomial), seed, buffer, 0, buffer.Length);
    }

    /// <summary> Рассчитывает контрольную сумму </summary>
    /// <param name="polynomial">Порождающий полином</param>
    /// <param name="seed">Начальное значение</param>
    /// <param name="buffer">Буфер данных</param>
    /// <returns>Контрольная сумма</returns>
    public static uint Compute(uint polynomial, uint seed, byte[] buffer)
    {
        return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
    }

    /// <summary> Инициализирует таблицу со значением полинома для каждого значения байта, чтоб не расчитывать их в процессе </summary>
    /// <param name="polynomial">Порождающий полином</param>
    private static uint[] InitializeTable(uint polynomial)
    {
        if (polynomial == DefaultPolynomial && defaultTable != null)
            return defaultTable;

        uint[] createTable = new uint[256];
        for (int i = 0; i < 256; i++)
        {
            uint entry = (uint)i;
            for (int j = 0; j < 8; j++)
            {
                if ((entry & 1) == 1)
                    entry = (entry >> 1) ^ polynomial;
                else
                    entry = entry >> 1;
            }

            createTable[i] = entry;
        }

        if (polynomial == DefaultPolynomial)
            defaultTable = createTable;

        return createTable;
    }

    private static uint CalculateHash(uint[] table, uint seed, byte[] buffer, int start, int size)
    {
        uint crc = seed;
        for (int i = start; i < size; i++)
        {
            unchecked
            {
                crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff];
            }
        }
        return crc;
    }

    /// <summary> Преобразует результат вычисления хеша в 4 байта с инвертированием битов </summary>
    private static byte[] UInt32ToBigEndianBytes(uint x)
    {
        return new byte[] {
            (byte)((x >> 24) & 0xff),
            (byte)((x >> 16) & 0xff),
            (byte)((x >> 8) & 0xff),
            (byte)(x & 0xff)
        };
    }

    /// <summary> Рассчитывает контрольную сумму файла и возвращает её в виде 16 битного значения в строке </summary>
    public static string Get(string file)
    {
        Crc32 crc32 = new Crc32();
        string hash = string.Empty;

        using (FileStream fs = File.Open(file, FileMode.Open))
        {
            foreach (byte b in crc32.ComputeHash(fs))
            {
                hash += b.ToString("x2").ToLower();
            }
        }
        return hash;
    }
}
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39784872
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CRC32 медленно считается. В инете нашел алгоритм попроще. Если в инете не наврали, то используется для расчет хэша строк у МС в С++.
Код: plaintext
1.
2.
3.
4.
5.
uint32_t hash32(const char* str) {
	uint32_t h = 0;
	while (*str) h = (h << 5) + h + *str++;
	return h;
}


Я слегка модифицировал под расчет хэша заданного блока памяти
Код: plaintext
1.
2.
3.
4.
5.
6.
uint32_t hash32(const void* data, size_t len, uint32_t prev = 0) {
	const char* str = (const char*) data;
	uint32_t h = prev;
	while (len--) h = (h << 5) + h + *str++;
	return h;
}


Думаю под C# несложно переписать. Можно переделать на 64 бита, просто заменить uint32_t на uint64_t
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39785011
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ого, тема получила продолжение, не ожидал.
Я взял для себя расчет мд5 и сравнение размера файла. Для меня не важно детальное сравнение файлов, важно знать, были ли изменения
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
public static string ComputeMd5Checksum(string path)
{
    using (var fs = File.OpenRead(path))
    using (MD5 md5 = new MD5CryptoServiceProvider())
    {
        var checkSum = md5.ComputeHash(fs);
        var result = BitConverter.ToString(checkSum).Replace("-", string.Empty);
        return result;
    }
}
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39785026
PinkCat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пав,

Для меня не важно детальное сравнение файлов, важно знать, были ли изменения
-----
Открой для себя:
https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=netframework-4.7.2
будешь получать нотификацию изменений по настроенным фильтрам.
По крайней мере не нужно будет сканить все каждые 10 минут.
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39785036
Супер_Пав
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PinkCat, у меня файлы в сети. FileWatcher я пробовал в 1ю очередь, были какие-то проблемы, точно уже не помню
...
Рейтинг: 0 / 0
Сравнение 2х картинок
    #39785056
PinkCat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Супер_Пав,

были какие-то проблемы
-----
Были, решал => работало.
Правда потом отказался - нашлось более приемлемое решение, чем следить за состоянием системы.
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Сравнение 2х картинок
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]