Hi. I tried to take a snapshot with a resolution of 128x64px and then copy it to the centre of a created image of 128x128px, but nothing, I canβt do it.
Here is an image of what I want to do:
Whatβs your code?
You need to allocate a second image buffer and then use the draw image method.
I canβt see any difference in the Frame Buffer preview (in the ide).
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.B128X64)
sensor.skip_frames(time = 2000)
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
img2 = image.Image(128, 128, sensor.RGB565, True)
img2 = img2.draw_image(img, 0, 32, 1, 1)
print(clock.fps())
By saving the image I can see that it worked, but I want it to be seen in the Frame Buffer preview for debugging.
Code:
import sensor, image, time, os
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.B128X64)
sensor.skip_frames(time = 2000)
clock = time.clock()
while True:
clock.tick()
img = sensor.snapshot()
img2 = image.Image(128, 128, sensor.RGB565)
img2.draw_image(img, 0 ,32)
img2.save(os.getcwd() + "image.jpg")
print(clock.fps())
I have seen that there is the Frame Buffer class, do I have to use it for the second image buffer?
Okay maybe I made something correct here, but I still canβt see the image I want in the frame buffer preview (I want the 128x128px image in the frame buffer preview).
import sensor, image, time, os
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.B128X64)
sensor.skip_frames(time = 2000)
img2 = sensor.alloc_extra_fb(128, 128, sensor.RGB565)
clock = time.clock()
while True:
clock.tick()
img = sensor.snapshot()
img2.draw_rectangle(0,0, 128, 128, (255,255,255), fill=True)
img2.draw_image(img, 0 ,32)
img2.save(os.getcwd() + "image.png")
print(clock.fps())
I donβt know if you can but what I do is
print(img.compressed_for_ide())
And then connect to the ide terminal to see the desire image β¦
It works for me
Hey, thanks for the reply. It works and it doesnβt work. It shows both the images (the one from the snapshot() and the one I call the function on) one after the other, and the frame rate goes down.
Here is what I get from executing the code:
Code:
import sensor, image, time, os
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.B128X64)
sensor.skip_frames(time = 2000)
img2 = sensor.alloc_extra_fb(128, 128, sensor.RGB565)
clock = time.clock()
while True:
clock.tick()
img = sensor.snapshot()
img2.draw_rectangle(0,0, 128, 128, (255,255,255), fill=True)
img2.draw_image(img, 0 ,32)
print(img2.compressed_for_ide())
print(clock.fps())
What I am trying to get is the preview of the 128x128px image only.
Please use the terminal to see the image you want. Not the ide preview.
Hi, the way our frame buffer architecture is setup the IDE is always trying to grab the first image.
Basically, when snapshot is called it jpeg compresses the current image in the primary frame buffer and sends that to the PC. Then it puts the next image from the camera in the frame buffer.
So, if you want to see your image you need to load it into the primary frame buffer.
import sensor, image, time, os
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.B128X64)
sensor.skip_frames(time = 2000)
img2 = sensor.alloc_extra_fb(128, 128, sensor.RGB565)
clock = time.clock()
while True:
clock.tick()
img = sensor.snapshot()
img2.draw_rectangle(0,0, 128, 128, (255,255,255), fill=True)
img2.draw_image(img, 0 ,32)
img.set(img2) # overwrite the old image and replace with the new one
print(clock.fps())
If you were just trying to crop/scale your image you can do that in place. Wanting to add black borders is an odd thing to do.
Whatβs the reason for wanting to do this? While it may look good it creates pixels that have no purpose in the image. This is why we donβt have a library function for it.
I have a wide angle lens and need to use OpenMV for object detection. I need to use square images for Edge Impulse training, but when I set the resolution a square resolution, like 128x128px, the edges of the image are cut off. So to avoid losing parts of the image, I thought about adding white pixels in the shortest axis. Maybe itβs not a brilliant idea, but it was the first thing that came to mind.
Thanks it works now. The reason I wanted it to be displayed in the ide preview was because of the dataset editor
The code does not work. I think the cause is that the pixel format is not the same.
Error: βOSError: Images not equal!β
So, just to note, the CNN will learn the black border and only respond to images that have that.
You 100% do not want to feed the CNN with a black border in the image. This will break the model.
You have to crop/scale your image such that the object of interest is in the 128x128 filed of view. Also, you need to avoid warping the image. So, the scale needs to maintain the aspect ratio.
Let me explain the problem from the beginning.
Goal
I have the Ultra Wide Angle Lens mounted on the OpenMV. I have to make it detect different letters. Iβm using Edge Impulse for the AI. On Edge Impulse, in the create impulse section, Iβm using the βObject Detection (Images)β as learning block. This force me to use images with a square resolution as input data both for training and usage of the AI model after the deployment.
In short what I need to do is detecting different letters in walls. Using Edge Impulse have me to use only images with square resolution.
Resolution problem
Here is the problem! If i set the a square resolution such as:
sensor.set_framesize(sensor.320x320px)
# or
sensor.set_framesize(sensor.128x128px)
# and so on...
I lose a significant left and right portion of image.
This is the image with a square resolution (320x320px):
Here is the image with a non square resolution (I used sensor.set_framesize(sensor.QVGA) to take this snapshot, which means 320x240px):
As you can see in the first photo, the one taken with the square resolution, it has been cut a very important portion of the image.
Our idea
Talking to my teacher, who is studying at university for a degree in AI, it turned out that cropping or squashing the image is not a good solution in this case. Therefore, we thought of adding white pixels in the shortest axis to obtain a square image and keep the original image intact.
Here is how the image with that βmanipulationβ should look like:
(I have used gray in this case just because the website background is white).
Given that for the training of the AI I have to select the area where the letters are for each image and for each letter, it does not matter if there is a a βbigβ area of only white pixels, as they are not in the letterβs square.
This is what I mean:
The white (gray in this case) area is never included in the red rectangles, so it will never be taken into account, it is like they are not there.
Reasons
So thatβs why Iβm trying to get the 320x240px snapshot drawn in the 320x320px white image. The reason of why I need it to be displayed in the frame buffer preview is to use the dataset editor to take the dataset for the Object Detection to detect the letters.
I hope i explained the problem in a more detailed way. If there is something you donβt understand or I badly explained, I will re-explain with pleasure.
Yes, I understand.
Question, are you doing FOMO or a classifier? Or both? A classifier would take a cropped image of each letter. FOMO would just find all the letters location.
Also, given the lens warp I suggest you use: img.lens_corr(1.8) to dewarp the lens. The CNN will have an easier time without the lens warping.
As for why set did not workβ¦ yeah, the images arenβt the same size. So, it has to do something more complex.
import sensor, image, time, os
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.B128X64)
sensor.skip_frames(time = 2000)
img2 = sensor.alloc_extra_fb(128, 128, sensor.RGB565)
clock = time.clock()
while True:
clock.tick()
img = sensor.snapshot()
img2.draw_rectangle(0,0, 128, 128, (255,255,255), fill=True)
img2.draw_image(img, 0 ,32)
img2.copy(copy_to_fb=img) # overwrite the old image and replace with the new one
print(clock.fps())
Yes Iβm using FOMO, in particular the model βFOMO (Faster Objects, More Objects) MobileNetV2 0.35β.
I see. Okay, well, I guess the above is all you need. FOMO spits out the class.
Regarding the lens shading issue. I noticed this. I will offer an SDK function later this year when I have time to write it to deal with correcting the lens vignetting. The camera sensor can actually do this itselfβ¦ but, itβs not documented well.
If I run the code, I get this error βOSError: The new image wonβt fit in the target frame buffer!β when executing the copy() method.
Yeah, because itβs bigger than the frame bufferβ¦
Try this:
import sensor, image, time, os
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.B128X64)
sensor.skip_frames(time = 2000)
sensor.set_framebuffers(1)
img2 = sensor.alloc_extra_fb(128, 128, sensor.RGB565)
clock = time.clock()
while True:
clock.tick()
img = sensor.snapshot()
img2.draw_rectangle(0,0, 128, 128, (255,255,255), fill=True)
img2.draw_image(img, 0 ,32)
img2.copy(copy_to_fb=img) # overwrite the old image and replace with the new one
print(clock.fps())
You have to set the number of frame buffer to 1 because by default the system will allocate 3 buffers for triple buffering to give you the best FPS. When it does this it canβt grow the frame buffers anymore. If you just have 1 then it can automatically figure out that it can grow the frame buffer so it will allow you to do so.
Sorry this is complex. When you start using more than 1 buffer in user space how our memory allocation works canβt really be hidden. Hereβs whatβs happening BTW.
ββββββββββββββββββββββββ
β β
β β
β Frame buffer 1 β
β β
β β
ββββββββββββββββββββββββ€
ββββββββββββββββββββββββ€
β β
β Frame buffer 2 β
β β
β β
ββββββββββββββββββββββββ€
β β
β β
β β
β β
β Frame Buffer 3 β
β β
β β
ββββββββββββ¬ββββββββββββ€
β β β
β β β
β β β
β β β
β βΌ β
β β
β β
β Free Space β
β β
β β
β β
β β
β β
β β² β
β β β
β β β
β β β
β β β
β β β
ββββββββββββ΄ββββββββββββ€
β β
β β
β Allocated FB β
β β
ββββββββββββββββββββββββ
So, in triple buffer mode your frame buffer canβt grow. If you just had one then it could. Your allocated frame buffer grows from the bottom.
When you execute a function it will then allocate RAM in that free space up until it hits the frame buffer area where images from the camera are stored. Note that our DMA driver in triple buffer mode is automatically updating frame buffers in the background to give you the fastest FPS while the processor works on 1 of the three.
We used this stack system instead of malloc because itβs MUCH faster to allocate and deallocate RAM in large amounts without wasting any space.
The MicroPython heap where MicroPython objects are stored is a heap though. Because of this you donβt want to allocate large objects in it since it can become fragmented and etc. We keep the frame buffer memory area separate for this reason.