Как я могу преобразовать массив целых чисел изображения JPG в изображение JPG? - PullRequest
1 голос
/ 21 января 2020

У меня установлена ​​камера на роботе. Короче говоря, камера выводит двоичный массив, который, на мой взгляд, является потоком в формате JPG. Я говорю это, так как многие методы в библиотеке, которую я использую, дают подсказку, что она кодируется в формате JPG, а первые и последние 2 байта равны 255 216 и 255 217 соответственно, которые являются магическими числами c формата файла JPG.

Как преобразовать этот массив целых чисел в файл JPG в Python?

Я попытался записать массив целых чисел в файл .JPG, но файл помечен как поврежденный.

Короче говоря, у меня есть ArduCam, подключенная к esp8266 (буквально плата Arduino, которая может подключаться к WiFi). У меня есть скрипт, который захватывает фотографию и загружает необработанные данные изображения на сервер, расположенный на esp8266. Вот основной метод, который я использую:

void camCapture(ArduCAM myCAM) {

 WiFiClient client = server.client(); // ignore this stuff
 uint32_t len  = myCAM.read_fifo_length();
 if (len >= MAX_FIFO_SIZE) //8M
 {
   Serial.println(F("Over size."));
 }
 if (len == 0 ) //0 kb
 {
   Serial.println(F("Size is 0."));
 }
 myCAM.CS_LOW();
 myCAM.set_fifo_burst();
 if (!client.connected()) return;
 String response = "[";
 i = 0;

 while ( len-- ) // this is where the raw image is collection
 {
   temp_last = temp;
   temp =  SPI.transfer(0x00);
   //Read JPEG data from FIFO
   if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while,
   {
     buffer[i++] = temp;  //save the last  0XD9
     response += String(int(temp)) + "], ";
     response += String(i);
     if (!client.connected()) break;
     Serial.print(String(i));
     server.send(200,"text/plain",response); // this is where the image is uploaded
     is_header = false;
     i = 0;
     myCAM.CS_HIGH();
     break;
   }
   if (is_header == true)
   {
     //Write image data to buffer if not full
     if (i < bufferSize)
       buffer[i++] = temp;
     else
     {
       //Write bufferSize bytes image data to file
       if (!client.connected()) break;
       i = 0;
       buffer[i++] = temp;
     }
     response += String(int(temp)) + ",";
   }
   else if ((temp == 0xD8) & (temp_last == 0xFF))
   {
     is_header = true;
     buffer[i++] = temp_last;
     buffer[i++] = temp;
     response += String(int(temp_last)) + "," + String(int(temp)) + ",";
   }
 }
}

Необработанные данные изображения выглядят так:

255,216,255,224,0,16,74,70,73,70,0,1,1,1,0,0,0,0,0,0,255,219,74,74,74,74,74,74,74,74,74,74,74,74,74,74 [...] 64,143,255,217

Теперь я знаю, что jpeg-файлы начинаются и заканчиваются 255,216 и 255,217 соответственно. Так что я вижу это как хороший знак. Кроме того, когда я использую код jpeg html, он фактически преобразует необработанные данные изображения в фактическое изображение.

Вот мой python скрипт, в котором я пытаюсь декодировать необработанные данные изображения в файл .jpg:

import cv2 

with open('img.txt') as file: # this is where I keep the raw image data
    img = file.read()


img = img.split(',')
img = [int(i) for i in img]
tmpfile = open("tmp.jpg", "wb")
for i in img:
    tmpfile.write(bytes(i))
tmpfile.close()

img = cv2.imread('tmp.jpg')
print(img)
cv2.imshow('img',img)
cv2.waitKey(0)

1 Ответ

1 голос
/ 21 января 2020

Вы выгружаете строковое представление значений (то есть "2", "5" и "5" вместо 0xFF) в файл, поскольку bytes() преобразует ваш int в байтовую строку. Вы могли заметить, что по размеру файла он не будет соответствовать количеству значений в tmp.txt.

. Правильный способ записи байтов в файл:

import struct

...
for i in img:
    tmpfile.write(struct.pack("B", i))
...

Поскольку в этом случае вы работаете с 8-битными значениями, вы также можете использовать chr(i).

...