Issue in converting the Pixels values to image

I'm working on the esp32 cam this is the setting of cam

config.pixel_format = PIXFORMAT_GRAYSCALE;
config.frame_size = FRAMESIZE_QQVGA;

and I'm trying to get on the pixels values from this code

fb = esp_camera_fb_get();
for (int i = 0; i < fb->len; i++){
Serial.print(fb->buf[i]);
Serial.print(",");
}
the output in serial monitor something like this

117,111,124,124,120,140,142,157,167,172,184,190,194,188,182,185,188,1

I used this code in python to convert txt file to image

Open image file, slurp the lot

contents = Path('C://Users//hp//Desktop//g120.txt').read_text()

Make a list of anything that looks like numbers using a regex...

... taking first as height, second as width and remainder as pixels

h, w, *pixels = re.findall(r'[0-9]+', contents)

Now make pixels into Numpy array of uint8 and reshape to correct height, width and depth

na = np.array(pixels, dtype=np.uint8).reshape((int(h),int(w)))

Now make the Numpy array into a PIL Image and save

Image.fromarray(na).save('C://Users//hp//Desktop//jpppphexresult.jpg')

but this error is show

na = np.array(pixels, dtype=np.uint8).reshape((int(h),int(w),3))
ValueError: cannot reshape array of size 1121989 into shape (117,111,3)

Now I need any way to convert these values to image to see if I'm in safe side or not ? any advice please?

This is the code.

#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h> // read and write from flash memory

// define the number of bytes you want to access
#define EEPROM_SIZE 1

// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27

#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22

int pictureNumber = 0;

void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector

Serial.begin(115200);
//Serial.setDebugOutput(true);
//Serial.println();

camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;

config.pixel_format = PIXFORMAT_GRAYSCALE;

if(psramFound()){
//config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.frame_size = FRAMESIZE_QQVGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}

// Init Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}

Serial.println("Starting SD Card");
if(!SD_MMC.begin()){
Serial.println("SD Card Mount Failed");
return;
}

uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD Card attached");
return;
}

camera_fb_t * fb = NULL;

// Take Picture with Camera
fb = esp_camera_fb_get();
for (int i = 0; i < fb->len; i++){
Serial.print(fb->buf[i]);
Serial.print(",");}

if(!fb) {
Serial.println("Camera capture failed");
return;
}
// initialize EEPROM with predefined size
EEPROM.begin(EEPROM_SIZE);
pictureNumber = EEPROM.read(0) + 1;

// Path where new picture will be saved in SD Card
String path = "/picture" + String(pictureNumber) +".png";

fs::FS &fs = SD_MMC;
Serial.printf("Picture file name: %s\n", path.c_str());

File file = fs.open(path.c_str(), FILE_WRITE);
if(!file){
Serial.println("Failed to open file in writing mode");
}
else {
file.write(fb->buf, fb->len); // payload (image), payload length
Serial.printf("Saved file to path: %s\n", path.c_str());
EEPROM.write(0, pictureNumber);
EEPROM.commit();
}

file.close();

esp_camera_fb_return(fb);

// Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
rtc_gpio_hold_en(GPIO_NUM_4);

delay(2000);
Serial.println("Going to sleep now");
delay(2000);
esp_deep_sleep_start();
Serial.println("This will never be printed");
}

void loop() {

}

did you forget to print h and w before the pixels' value?

Yes I did not print h and w , pardon, why I need to that ? and how can I do?

this has little to do with Arduino, it's more a question for a Python forum...

when you do

h, w, *pixels = re.findall(r'[0-9]+', contents)

you use regular expression pattern matching.
h takes the first value from contents
w takes the second value from contents
pixels is the rest
so in your case you use the first two values 117 and 111 and height and width...

then you use h and w to reshape the array

na = np.array(pixels, dtype=np.uint8).reshape((int(h),int(w),3))

==> the size has to make sense, here it does not...

try this to see it:

import re
import numpy
contents = "6,3,117,111,124,124,120,140,142,157,167,172,184,190,194,188,182,185,188,1"
h, w, *pixels = re.findall(r'[0-9]+', contents)
print(h)
print(w)
print(pixels)
na = numpy.array(pixels, dtype=numpy.uint8).reshape((int(h),int(w),1))
print(na)

h will be 6 and w will be 3

pixels will be ['117', '111', '124', '124', '120', '140', '142', '157', '167', '172', '184', '190', '194', '188', '182', '185', '188', '1']

and na will be

[[[117]
  [111]
  [124]]

 [[124]
  [120]
  [140]]

 [[142]
  [157]
  [167]]

 [[172]
  [184]
  [190]]

 [[194]
  [188]
  [182]]

 [[185]
  [188]
  [  1]]]

the size is available, just print height and width before spitting out the pixels, this is the struct representing the framebuffer

typedef struct {
    uint8_t * buf;              /*!< Pointer to the pixel data */
    size_t len;                 /*!< Length of the buffer in bytes */
    size_t width;               /*!< Width of the buffer in pixels */
    size_t height;              /*!< Height of the buffer in pixels */
    pixformat_t format;         /*!< Format of the pixel data */
    struct timeval timestamp;   /*!< Timestamp since boot of the first DMA buffer of the frame */
} camera_fb_t;

Ok, thanks a lot for this information, but I have the same problem I can't save the file as image in my computer .

na = numpy.array(pixels, dtype=numpy.uint8).reshape((int(h),int(w),3))
ValueError: cannot reshape array of size 1121989 into shape (117,111,3)

are 117 and 111 the height and width of your image and do you have 3 bytes per pixel (given you mentioned PIXFORMAT_GRAYSCALE)?

try spitting the data out this way:

fb = esp_camera_fb_get();
Serial.print(fb->height); Serial.write(',');  // write the height 
Serial.print(fb->width); Serial.write(',');   // write the width
for (int i = 0; i < fb->len; i++){            // dump the pixels' value
  Serial.print(fb->buf[i]);
  if (i != fb->len -1) Serial.write(',');
  else Serial.println();
}

Just a minute I will share all the code

I updated my code but the problem is still

After I used this code

fb = esp_camera_fb_get();
Serial.print(fb->height); Serial.write(',');  // write the height 
Serial.print(fb->width); Serial.write(',');   // write the width
for (int i = 0; i < fb->len; i++){            // dump the pixels' value
  Serial.print(fb->buf[i]);
  if (i != fb->len -1) Serial.write(',');
  else Serial.println();
}

The same problem I can't show the image

na = np.array(pixels, dtype=np.uint8).reshape((int(h),int(w),3))
ValueError: cannot reshape array of size 19200 into shape (120,160,3)

I'm tried to save the txt file directly as image.jpg or any other extension but when open the image I get "We can't open this file" ! :frowning:

120x160 = 19200 pixels
since you are in gray scale, you likely have only 1 byte per pixel ➜ 19200 bytes
(try printing also fb->len to be sure)

So you should not say 3 when you reshape the array. 1 would likely make more sense.

yes I printed fb->len and this equal to 19200

I used
na = np.array(pixels, dtype=np.uint8).reshape((int(h),int(w),1))

and I have this output

Traceback (most recent call last):

File "C:\Users\hp\AppData\Local\Programs\Python\Python38\lib\site-packages\PIL\Image.py", line 2835, in fromarray

mode, rawmode = _fromarray_typemap[typekey]

KeyError: ((1, 1, 1), '|u1')

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

File "c:\Users\hp\Desktop\workpy\A.py", line 44, in

Image.fromarray(na).save('C://Users//hp//Desktop//result.jpg')

File "C:\Users\hp\AppData\Local\Programs\Python\Python38\lib\site-packages\PIL\Image.py", line 2837, in fromarray

raise TypeError("Cannot handle this data type: %s, %s" % typekey) from e

TypeError: Cannot handle this data type: (1, 1, 1), |u1

So it’s only 1 byte per pixel


na = np.array(pixels, dtype=np.uint8).reshape((int(h),int(w),1))

But I did not get on the image!

I changed to (config.pixel_format = PIXFORMAT_RGB565; )

the len of captured image = 38400

I used this in python
na = np.array(pixels, dtype=np.uint8).reshape((int(h),int(w),2))

know I get on the image but when opened it be like grayscale ? I mean it is no colorful ? why?

opened with what ? You need to tell your viewer how to interpret the data

So, I returned to original question how to get on the image from txt file!! :frowning:

don't answer with a question... how do you display the image ?
(please edit and add code tags to your posts)

I answered in the above, I used the same python code , read txt file and then get on result.png from python code then opened this image by image photo viewer on my PC.

are you generating a png file? it requires a header. are you using Python Imaging Library (PIL)?

please add code tags to your posts ➜ read How to get the best out of this forum

if you mean png in python code, yes , because just this extension generate image from (PIXFORMAT_RGB565).
and yes I used PIL
Image.fromarray(na).save('C://Users//hp//Desktop//newrgbresult.png')

you would probably need to define the mode but I don't think RGB565 is supported, you probably will need to map to 8 bit RGB before building the image

have you looked at frombytes or frombuffer

PLEASE modify your first post and add code tags.