Scaling an image from FHD to VGA

I am using the openmv H7 plus.
I want to:

  1. take a full size FHD image
  2. save that image frame to a mjpeg file on the sd card
  3. scale the image frame to a VGA 640x480 image
  4. send the bytes of the smaller image over serial to my controller board.

I am able to accomplish all the steps except for step three. I’m trying to find a way to scale the image down to the smaller resolution before sending it over serial. I’ve looked into image.scale in the docs but the x_scale parameter seems to be a float parameter and I’m not sure what it is expecting. The x_size parameter I’ve tried but I run into a out of memory error. Is there a way to accomplish the image scaling or another route I can take to accomplish a similar effect?

x_scale is literally the thing to multiply the resolution by: 1280 → 640 == 1/2 == 0.5

x_size should have done what you want. Can you post the code snippet? x_size/scale just get converted to an internal parameter that does the job. So, if you are getting an out of memory error on one you’ll get it on the other.

The issue could be related to you trying to scale a jpeg image?

The error I’m getting: “MemoryError: memory allocation failed, allocating 614400 bytes”
The code I’m using:

def init_board():
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.FHD)
    sensor.skip_frames(time=2000)


init_board()
clock = time.clock()
m = mjpeg.Mjpeg("movie.mjpeg")

# 1. UART Read -- wait for signal to take snapshot
# 2. Take snapshot -- write it to the mjpeg on the SD card
# 3. Downscale the image -- write it over serial bus

protocol = Protocol()


def save_image():
    frame = sensor.snapshot()
    print(m.width())
    m.add_frame(frame)
    reduced_img = frame.scale(x_size=640, y_size=480, copy=True)
    return reduced_img


while (True):
    try:
        command = protocol.command()
        if command == Protocol.CAPTURE:
            print(command)
            save_image()
        if command == Protocol.STOP:
            break
    except OSError as e:
        print(str(e))

m.close(1)

The error hits on the same line where I scale the image down.

Oh, it’s because you are trying to copy that into the MicroPython heap which is only 256KB.

You need to either overwrite the current frame buffer with the down scaled image or alloc a new frame buffer and then target that by passing it as the argument to copy.

Just don’t pass the copy argument to overwrite the current frame buffer.

Thank you! I tried that and it worked. I saved the high quality image and still have the down scaled version to send over the serial bus.

Can you post the code for others?

Like you said all I had to do was remove the copy argument from the scale() function. Other than that the code is identical to what I posted above.

def init_board():
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.FHD)
    sensor.skip_frames(time=2000)


init_board()
clock = time.clock()
m = mjpeg.Mjpeg("movie.mjpeg")

protocol = Protocol()


def save_image():
    frame = sensor.snapshot()
    print(m.width())
    m.add_frame(frame)
    frame.scale(x_size=640, y_size=480)
    return frame