2017-02-14 23 views
2

Я хотел бы получить доступ к значению каждого отдельного значения пикселя PNG-изображения 16UC1, которое я получаю в виде байта [].Чтение массива байтов данных ROS CompressedImage в C#

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

Я могу работать с "типичным" bgr8 в формате JPG/PNG массивом байт просто:

private static Bitmap getBitmap(byte[] array) 
{ 
return new Bitmap(new MemoryStream(array)); 
} 

Я пробовал много вещей для 16UC1-формата. Самое большое, что я получил:

private Bitmap getBitmap(byte[] array) 
{ 
    var bitmap = new Bitmap(640,480,PixelFormat.Format16bppRgb555); 

    var bitmapData = bitmap.LockBits(new Rectangle(0, 0, 640, 480), ImageLockMode.WriteOnly, PixelFormat.Format16bppRgb555); 
    System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, array, 0, array.Length); 
    bitmap.UnlockBits(bitmapData); 

    return bitmap; 
} 

это, по крайней мере, возвращает растровое изображение, хотя оно полностью черное. Попытка PixelFormat.Format16bppGrayScale вместо PixelFormat.Format16bppRgb555 дает мне «Общая ошибка в GDI +».

При записи массива байтов в файл, например. от

File.WriteAllBytes(filename, array); 

Я вижу изображение с изображениями, такими как IrfanView, хотя средство просмотра фотографий Windows не работает.

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


Update: Я начал использовать Emgu.CV и применяя imdecode, как Дэн предложил ниже.

private Bitmap getCompressedDepthBitmap(byte[] data) 
{ 
    Mat result = new Mat(new Size(640, 480), DepthType.Cv16U, 1); 
    CvInvoke.Imdecode(data,LoadImageType.AnyDepth, result); 
    return result.Bitmap;   
} 

Это снова дает мне черное изображение. (Сохраняя массив байт с помощью WriteAllBytes я вижу полезное содержание.) Я также попытался

Image<Gray, float> image = result.ToImage<Gray, float>(); 
image.Save(Path.Combine(localPath, "image.png")); 

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

Спасибо за ваш интерес и поддержку!

+0

Если это 'CV_16UC1' (то есть 1 канал, то есть оттенки серого), то почему вы делаете растровый RGB? –

+0

Привет, Дэн, чем вы за ваш комментарий! Вы хотите утроить каждое значение, а затем разобрать массив байтов Bitmap? Мое изображение - сжатый png-файл. Его размер варьируется и намного меньше, чем 640 * 480 * 2 байта. Я не знаю, какие байты соответствуют полутоновой шкале. – analogtwin

+0

О, это еще не расшифровано? Вам нужно использовать ['imdecode'] (http://www.emgu.com/wiki/files/3.1.0/document/html/c284605a-35ec-b40e-c44d-c83037a6a325.htm) ... –

ответ

0

После нескольких часов и часов потраченного впустую рабочего времени и отчаяния я, наконец, нашел решение ...

Одна важная вещь, мне не хватало в моем описании выше, что байт данных изображения [] исходит из из ROS sensor_msgs/CompressedImage.msg.

Байт данных данных, который должен содержать данные png, иногда начинается с 12-байтового заголовка; по-видимому, только если данные (1 канал) сжаты. Я быстро нашел эту информацию here.

Удаление этих пугающе obnoxous 12 байт и continung как обычно делает работу:

var bitmap = new Bitmap(new MemoryStream(dataSkip(12).ToArray())); 

 Смежные вопросы

  • Нет связанных вопросов^_^