Быстрый способ сравнения 2-байтовых массивов

Я загружаю изображения в формате jpeg так быстро, как только могу, на веб-службу (это требование, которое мне было дано).

Я использую асинхронный вызов веб-службы и вызываю его по таймеру.

Я пытаюсь максимально оптимизировать и стараюсь использовать для тестирования старый ноутбук. На нормальном/нормальном компе все ОК. На ноутбуке я получаю большое использование оперативной памяти.

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

Как вы можете видеть в приведенном ниже коде, я преобразовываю jpeg-изображение в массив байтов, а затем загружаю массив байтов.

Если я смогу уменьшить/сжать/заархивировать массив до свидания, я надеюсь, что это будет один из способов улучшить использование памяти.

Я знаю, что jpeg уже сжат, но если я сравню текущий массив байтов с предыдущим массивом байтов, то, загрузив разницу между этими массивами байтов, я, возможно, смогу сжать его еще больше на том основании, что некоторые значения байтов будут равны нулю.

Если бы я использовал кодировщик видео (который помог бы), я бы не работал в реальном времени так, как мне хотелось бы.

Есть ли оптимальный способ сравнения 2-байтовых массивов и вывода в 3-байтовый массив? Я огляделся, но не смог найти ответ, который мне понравился.

Это мой код на клиенте:

bool _uploaded = true;
private void tmrLiveFeed_Tick(object sender, EventArgs e)
{
  try
  {
      if (_uploaded)
      {
        _uploaded = false;
          _live.StreamerAsync(Shared.Alias, imageToByteArray((Bitmap)_frame.Clone()), Guid.NewGuid().ToString()); //web service being called here
      }
  }
  catch (Exception _ex)
  {
      //do some thing but probably time out error here
  }
}

//web service has finished the client invoke 
void _live_StreamerCompleted(object sender, AsyncCompletedEventArgs e)
{
 _uploaded = true; //we are now saying we start to upload the next byte array
}

private wsLive.Live _live = new wsLive.Live(); //web service 
private byte[] imageToByteArray(Image imageIn)
{
  MemoryStream ms = new MemoryStream();
  imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);  //convert image to best image compression
  imageIn.Dispose();
  return ms.ToArray();
}

Спасибо...


person Andrew Simpson    schedule 20.11.2013    source источник
comment
Вы можете сделать это через md5.   -  person kostas ch.    schedule 20.11.2013
comment
Ваше решение stackoverflow.com/questions/3410276/   -  person kostas ch.    schedule 20.11.2013
comment
привет, спасибо, что нашли время ответить. Разве это не шифрование, а не сжатие? Спасибо   -  person Andrew Simpson    schedule 20.11.2013
comment
Вы можете использовать md5 так, как хотите. Если вы измените байт, он создаст другой md5. поэтому вы можете сравнить jsut со строкой md5, которая будет создана из 2 байтов []. Лично я использую его все время по этой причине, чтобы сравнивать вещи.   -  person kostas ch.    schedule 20.11.2013
comment
Понимаю. Я найду время, чтобы посмотреть на него очень скоро и вернуться к вам. Спасибо!   -  person Andrew Simpson    schedule 20.11.2013
comment
Пожалуйста. Я надеюсь, что мой комментарий поможет вам.   -  person kostas ch.    schedule 20.11.2013
comment
Привет, извините за то, что я немного тусклый, но вы предлагаете мне преобразовать предыдущие и текущие изображения в хэш md5 и сравнить? Как мне получить разницу в новый массив байтов, чтобы показать изменения в изображениях в новом изображении? На сервере я хочу преобразовать массив байтов обратно в jpeg. Это только для сравнения? Спасибо   -  person Andrew Simpson    schedule 20.11.2013
comment
Сорри за непонимание, я не понял, что вы хотите показать различия. Этот способ просто для сравнения вещей. Конечно, вы не можете указать на различия.   -  person kostas ch.    schedule 20.11.2013
comment
Ок - нп. думал что-то пропустил..   -  person Andrew Simpson    schedule 20.11.2013
comment
@косташ. Я попробовал md5, чтобы посмотреть, есть ли разница между двумя изображениями. В 99% случаев я обнаружил, что md5s двух изображений не совпадают, и, таким образом, это говорит мне о наличии различий между двумя изображениями. Я предполагаю, что для обнаружения движения md5 не подойдет для такой задачи? просто любопытно.   -  person Andrew Simpson    schedule 22.11.2013
comment
Наверное, не подходит, потому что в движении ваше изображение будет постоянно меняться. Например, если у вас есть камера вне дома и вы делаете снимки, если солнце изменит свое положение, изображение будет другим.   -  person kostas ch.    schedule 22.11.2013
comment
Хорошо - спасибо, что ответили мне   -  person Andrew Simpson    schedule 22.11.2013


Ответы (2)


Как сказал C.Evenhuis, файлы JPEG сжимаются, и изменение даже нескольких пикселей приводит к совершенно другому файлу. Так что сравнивать получившиеся JPEG-файлы бесполезно.

НО вы можете сравнить свои объекты изображения - быстрый поиск приводит к нахождению этого:

unsafe Bitmap PixelDiff(Bitmap a, Bitmap b)
{
    Bitmap output = new Bitmap(a.Width, a.Height, PixelFormat.Format32bppArgb);
    Rectangle rect = new Rectangle(Point.Empty, a.Size);
    using (var aData = a.LockBitsDisposable(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
    using (var bData = b.LockBitsDisposable(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
    using (var outputData = output.LockBitsDisposable(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb))
    {
        byte* aPtr = (byte*)aData.Scan0;
        byte* bPtr = (byte*)bData.Scan0;
        byte* outputPtr = (byte*)outputData.Scan0;
        int len = aData.Stride * aData.Height;
        for (int i = 0; i < len; i++)
        {
            // For alpha use the average of both images (otherwise pixels with the same alpha won't be visible)
            if ((i + 1) % 4 == 0)
                *outputPtr = (byte)((*aPtr  + *bPtr) / 2);
            else
                *outputPtr = (byte)~(*aPtr ^ *bPtr);

            outputPtr++;
            aPtr++;
            bPtr++;
        }
    }
    return output;
}
person Jakub Szułakiewicz    schedule 20.11.2013
comment
Привет, это выглядит интересно. Только что зашел, скоро посмотрю как следует. Хорошо, спасибо. - person Andrew Simpson; 20.11.2013
comment
Привет, я посмотрел и использовал этот код, но он не дал мне того, что я хочу. Я сравнил 2 изображения, и 3-е было очень белым. Вместо этого я посмотрю на OpenCV. Спасибо за ваше время, хотя - person Andrew Simpson; 20.11.2013

Если ваша цель — выяснить, содержат ли два байтовых массива точно одни и те же данные, вы можете создать хэш MD5 и сравнить их, как предложили другие. Однако в своем вопросе вы упоминаете, что хотите загрузить разницу, что означает, что результат сравнения должен быть больше, чем просто да/нет.

Поскольку файлы JPEG уже сжаты, малейшее изменение изображения может привести к большой разнице в двоичных данных. Я не думаю, что любые два файла JPEG содержат двоичные данные, достаточно похожие, чтобы их можно было легко сравнить.

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

Короче говоря, я не думаю, что получение двоичной разницы между файлами JPEG улучшит размер отправляемых данных.

person C.Evenhuis    schedule 20.11.2013
comment
Привет, спасибо за ответ. Очень признателен. Я оставлю вопрос открытым в надежде, что у кого-то будет другой взгляд на него, но я понимаю, что вы сказали. Спасибо - person Andrew Simpson; 20.11.2013