Merge pull request #927 from kwagyeman/kwabena/larry_scaling_code

Add new image scaling pipeline
This commit is contained in:
Ibrahim Abd Elkader 2020-10-19 03:37:20 +02:00 committed by GitHub
commit 32f8ef3172
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 3977 additions and 588 deletions

View File

@ -0,0 +1,71 @@
# Image Drawing Alpha Blending Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
hint = image.BICUBIC # image.BILINEAR image.BICUBIC
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
alpha_div = 1
alpha_value = 0
alpha_step = 2
x_bounce = sensor.width()//2
x_bounce_toggle = 1
y_bounce = sensor.height()//2
y_bounce_toggle = 1
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#img.to_grayscale()
#img.to_bitmap()
img.draw_image(big_img, x_bounce, y_bounce,
rgb_channel=-1, alpha=alpha_value//alpha_div,
hint=hint|image.CENTER)
x_bounce += x_bounce_toggle
if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle
alpha_value += alpha_step
if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step
print(clock.fps())

View File

@ -0,0 +1,81 @@
# Image Drawing Color Table with Alpha Blending Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
hint = image.BICUBIC # image.BILINEAR image.BICUBIC
# RGB channel extraction is done after scaling normally, this
# may produce false colors. Set this flag to do it before.
#
hint |= 0 # image.EXTRACT_RGB_CHANNEL_FIRST
# Color table application is done after scaling normally, this
# may produce false colors. Set this flag to do it before.
#
hint |= 0 # image.APPLY_COLOR_PALETTE_FIRST
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
alpha_div = 1
alpha_value = 0
alpha_step = 2
x_bounce = sensor.width()//2
x_bounce_toggle = 1
y_bounce = sensor.height()//2
y_bounce_toggle = 1
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#img.to_grayscale()
#img.to_bitmap()
img.draw_image(big_img, x_bounce, y_bounce,
rgb_channel=-1, alpha=alpha_value//alpha_div,
color_palette=sensor.PALETTE_IRONBOW, hint=hint|image.CENTER)
x_bounce += x_bounce_toggle
if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle
alpha_value += alpha_step
if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step
print(clock.fps())

View File

@ -0,0 +1,75 @@
# Image Drawing Alpha Table Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
hint = image.BICUBIC # image.BILINEAR image.BICUBIC
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
alpha_lut = image.Image(256, 1, sensor.GRAYSCALE)
for i in range(256):
alpha_lut.set_pixel(i, 0, 255 if i > 127 else 0)
alpha_div = 1
alpha_value = 0
alpha_step = 2
x_bounce = sensor.width()//2
x_bounce_toggle = 1
y_bounce = sensor.height()//2
y_bounce_toggle = 1
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#img.to_grayscale()
#img.to_bitmap()
img.draw_image(big_img, x_bounce, y_bounce,
rgb_channel=-1, alpha=alpha_value//alpha_div,
alpha_palette=alpha_lut, hint=hint|image.CENTER)
x_bounce += x_bounce_toggle
if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle
alpha_value += alpha_step
if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step
print(clock.fps())

View File

@ -0,0 +1,85 @@
# Image Drawing Color Table with Alpha Table Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
hint = image.BICUBIC # image.BILINEAR image.BICUBIC
# RGB channel extraction is done after scaling normally, this
# may produce false colors. Set this flag to do it before.
#
hint |= 0 # image.EXTRACT_RGB_CHANNEL_FIRST
# Color table application is done after scaling normally, this
# may produce false colors. Set this flag to do it before.
#
hint |= 0 # image.APPLY_COLOR_PALETTE_FIRST
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
alpha_lut = image.Image(256, 1, sensor.GRAYSCALE)
for i in range(256):
alpha_lut.set_pixel(i, 0, 255 if i > 127 else 0)
alpha_div = 1
alpha_value = 0
alpha_step = 2
x_bounce = sensor.width()//2
x_bounce_toggle = 1
y_bounce = sensor.height()//2
y_bounce_toggle = 1
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#img.to_grayscale()
#img.to_bitmap()
img.draw_image(big_img, x_bounce, y_bounce,
rgb_channel=-1, alpha=alpha_value//alpha_div,
color_palette=sensor.PALETTE_IRONBOW, alpha_palette=alpha_lut, hint=hint|image.CENTER)
x_bounce += x_bounce_toggle
if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle
alpha_value += alpha_step
if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step
print(clock.fps())

View File

@ -0,0 +1,69 @@
# Image Scaling Down Drawing Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
# DISABLE THE FRAME BUFFER TO SEE THE REAL FPS
import sensor, image, time
up_hint = 0 # image.BILINEAR image.BICUBIC
down_hint = image.AREA # image.BILINEAR image.BICUBIC image.AREA
bounce_div = 128
medium_img = image.Image(32, 32, sensor.RGB565, copy_to_fb=True)
#medium_img.to_grayscale()
#medium_img.to_bitmap()
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
big_img = image.Image(128, 128, sensor.RGB565)
big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32, hint=up_hint)
#big_img.to_grayscale()
#big_img.to_bitmap()
x_bounce = 0
x_bounce_toggle = 0
y_bounce = 0
y_bounce_toggle = 0
clock = time.clock()
while(True):
clock.tick()
medium_img.clear()
medium_img.draw_image(big_img,
x_bounce // bounce_div, y_bounce // bounce_div,
x_scale=0.25, y_scale=0.25,
hint=down_hint)
sensor.flush()
x_bounce += x_bounce_toggle
if abs(x_bounce // bounce_div) >= (medium_img.width()*1.1): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce // bounce_div) >= (medium_img.height()*1.1): y_bounce_toggle = -y_bounce_toggle
print(clock.fps())

View File

@ -0,0 +1,63 @@
# Image Scaling Up Drawing Test
#
# This script tests the performance and quality of the draw_image()
# method which can perform nearest neighbor, bilinear, bicubic, and
# area scaling along with color channel extraction, alpha blending,
# color palette application, and alpha palette application.
# DISABLE THE FRAME BUFFER TO SEE THE REAL FPS
import sensor, image, time
hint = 0 # image.BILINEAR image.BICUBIC
bounce_div = 32
big_img = image.Image(128, 128, sensor.RGB565, copy_to_fb=True)
#big_img.to_grayscale()
#big_img.to_bitmap()
small_img = image.Image(4, 4, sensor.RGB565)
small_img.set_pixel(0, 0, (0, 0, 127))
small_img.set_pixel(1, 0, (47, 255, 199))
small_img.set_pixel(2, 0, (0, 188, 255))
small_img.set_pixel(3, 0, (0, 0, 127))
small_img.set_pixel(0, 1, (0, 176, 255))
small_img.set_pixel(1, 1, (222, 0, 0 ))
small_img.set_pixel(2, 1, (50, 255, 195))
small_img.set_pixel(3, 1, (86, 255, 160))
small_img.set_pixel(0, 2, (255, 211, 0 ))
small_img.set_pixel(1, 2, (83, 255, 163))
small_img.set_pixel(2, 2, (255, 211, 0))
small_img.set_pixel(3, 2, (0, 80, 255))
small_img.set_pixel(0, 3, (255, 118, 0 ))
small_img.set_pixel(1, 3, (127, 0, 0 ))
small_img.set_pixel(2, 3, (0, 144, 255))
small_img.set_pixel(3, 3, (50, 255, 195))
#small_img.to_grayscale()
#small_img.to_bitmap()
x_bounce = 0
x_bounce_toggle = 0
y_bounce = 0
y_bounce_toggle = 0
clock = time.clock()
while(True):
clock.tick()
big_img.clear()
big_img.draw_image(small_img,
x_bounce // bounce_div, y_bounce // bounce_div,
x_scale=32, y_scale=32,
hint=hint)
sensor.flush()
x_bounce += x_bounce_toggle
if abs(x_bounce // bounce_div) >= (big_img.width()*1.1): x_bounce_toggle = -x_bounce_toggle
y_bounce += y_bounce_toggle
if abs(y_bounce // bounce_div) >= (big_img.height()*1.1): y_bounce_toggle = -y_bounce_toggle
print(clock.fps())

View File

@ -46,9 +46,9 @@
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline
#endif
#ifndef __STATIC_FORCEINLINE
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
#endif
#endif
#ifndef __NO_RETURN
#define __NO_RETURN __attribute__((__noreturn__))
#endif
@ -585,7 +585,7 @@ __STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask)
Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
Stack Pointer Limit register hence zero is returned always in non-secure
mode.
\details Returns the current value of the Process Stack Pointer Limit (PSPLIM).
\return PSPLIM Register value
*/
@ -630,7 +630,7 @@ __STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void)
Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
Stack Pointer Limit register hence the write is silently ignored in non-secure
mode.
\details Assigns the given value to the Process Stack Pointer Limit (PSPLIM).
\param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
*/
@ -767,7 +767,7 @@ __STATIC_FORCEINLINE uint32_t __get_FPSCR(void)
{
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
#if __has_builtin(__builtin_arm_get_fpscr)
#if __has_builtin(__builtin_arm_get_fpscr)
// Re-enable using built-in when GCC has been fixed
// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
/* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
@ -1159,6 +1159,23 @@ __extension__ \
})
/**
\brief Signed Saturate
\details Saturates a signed value.
\param [in] ARG1 Value to be saturated
\param [in] ARG2 Bit position to saturate to (1..32)
\param [in] ARG3 Right shift (0..31)
\return Saturated value
*/
#define __SSAT_ASR(ARG1,ARG2,ARG3) \
__extension__ \
({ \
int32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2, asr %3" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1), "I" (ARG3) ); \
__RES; \
})
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
@ -1175,6 +1192,23 @@ __extension__ \
})
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
\param [in] ARG1 Value to be saturated
\param [in] ARG2 Bit position to saturate to (0..31)
\param [in] ARG3 Right shift (0..31)
\return Saturated value
*/
#define __USAT_ASR(ARG1,ARG2,ARG3) \
__extension__ \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2, asr %3" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1), "I" (ARG3) ); \
__RES; \
})
/**
\brief Rotate Right with Extend (32 bit)
\details Moves each bit of a bitstring right by one bit.
@ -1863,6 +1897,14 @@ __STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1)
return(result);
}
__STATIC_FORCEINLINE uint32_t __UXTB16_RORn(uint32_t op1, uint32_t rotate)
{
uint32_t result;
__ASM volatile ("uxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) );
return result;
}
__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@ -1871,6 +1913,14 @@ __STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
return(result);
}
__STATIC_FORCEINLINE uint32_t __UXTAB_RORn(uint32_t op1, uint32_t op2, uint32_t rotate)
{
uint32_t result;
__ASM volatile ("uxtab %0, %1, %2, ROR %3" : "=r" (result) : "r" (op1), "r" (op2), "i" (rotate) );
return result;
}
__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
{
uint32_t result;
@ -1879,6 +1929,14 @@ __STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
return(result);
}
__STATIC_FORCEINLINE uint32_t __SXTB16_RORn(uint32_t op1, uint32_t rotate)
{
uint32_t result;
__ASM volatile ("sxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) );
return result;
}
__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@ -1887,6 +1945,14 @@ __STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
return(result);
}
__STATIC_FORCEINLINE uint32_t __SXTAB_RORn(uint32_t op1, uint32_t op2, uint32_t rotate)
{
uint32_t result;
__ASM volatile ("sxtab %0, %1, %2, ROR %3" : "=r" (result) : "r" (op1), "r" (op2), "i" (rotate) );
return result;
}
__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
{
uint32_t result;
@ -2043,7 +2109,7 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2)
return(result);
}
#if 0
#if 1
#define __PKHBT(ARG1,ARG2,ARG3) \
({ \
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
@ -2061,13 +2127,13 @@ __STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2)
__RES; \
})
#endif
/*
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
*/
__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
{
int32_t result;

View File

@ -142,7 +142,7 @@
#endif
// Enable FAST (20+ KBs).
#define IMLIB_ENABLE_FAST
// #define IMLIB_ENABLE_FAST
// Enable find_template()
#define IMLIB_FIND_TEMPLATE

View File

@ -142,7 +142,7 @@
#endif
// Enable FAST (20+ KBs).
#define IMLIB_ENABLE_FAST
// #define IMLIB_ENABLE_FAST
// Enable find_template()
#define IMLIB_FIND_TEMPLATE

View File

@ -93,7 +93,7 @@
#endif
// Enable get_similarity()
#define IMLIB_ENABLE_GET_SIMILARITY
// #define IMLIB_ENABLE_GET_SIMILARITY
// Enable find_lines()
#define IMLIB_ENABLE_FIND_LINES

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,9 @@
#include "collections.h"
#include "imlib_config.h"
extern void *unaligned_2_to_1_memcpy(void *dest, void *src, size_t n);
extern void *unaligned_memcpy(void *dest, void *src, size_t n);
#define IM_LOG2_2(x) (((x) & 0x2ULL) ? ( 2 ) : 1) // NO ({ ... }) !
#define IM_LOG2_4(x) (((x) & 0xCULL) ? ( 2 + IM_LOG2_2((x) >> 2)) : IM_LOG2_2(x)) // NO ({ ... }) !
#define IM_LOG2_8(x) (((x) & 0xF0ULL) ? ( 4 + IM_LOG2_4((x) >> 4)) : IM_LOG2_4(x)) // NO ({ ... }) !
@ -287,6 +290,50 @@ extern const int8_t yuv_table[196608];
#define COLOR_RGB565_TO_V(pixel) imlib_rgb565_to_v(pixel)
#endif
#define RGB565_TO_R8_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
__pixel = __pixel & 0xF8; /* RGB565 byte reversal fix */ \
__pixel | (__pixel >> 5); \
})
#define RGB565_TO_G8_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
__pixel = (__REV16(__pixel) >> 3) & 0xFC; /* RGB565 byte reversal fix */ \
__pixel | (__pixel >> 6); \
})
#define RGB565_TO_B8_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
__pixel = (__pixel >> 5) & 0xF8; /* RGB565 byte reversal fix */ \
__pixel | (__pixel >> 5); \
})
#define RGB565_TO_Y_FAST(rgb565) \
({ \
__typeof__ (rgb565) __rgb565 = (rgb565); \
int r = RGB565_TO_R8_FAST(__rgb565); \
int g = RGB565_TO_G8_FAST(__rgb565); \
int b = RGB565_TO_B8_FAST(__rgb565); \
((r * 38) + (g * 75) + (b * 15)) >> 7; /* 0.299R + 0.587G + 0.114B */ \
})
#define Y_TO_RGB565_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
int __rb_pixel = (__pixel >> 3) & 0x3F; \
int __rgb_pixel = (__rb_pixel * 0x0801) + ((__pixel << 3) & 0x7E0); \
__REV16(__rgb_pixel); /* RGB565 byte reversal fix */ \
})
#define Y_TO_RGB888_FAST(pixel) \
({ \
__typeof__ (pixel) __pixel = (pixel); \
pixel * 0x010101; \
})
#define COLOR_LAB_TO_RGB565(l, a, b) imlib_lab_to_rgb(l, a, b)
#define COLOR_YUV_TO_RGB565(y, u, v) imlib_yuv_to_rgb((y) + 128, u, v)
@ -560,9 +607,6 @@ float IMAGE_Y_RATIO = ((float) _source_rect->s.h) / ((float) _target_rect->s.h);
_row_ptr + ((_image->w + UINT32_T_MASK) >> UINT32_T_SHIFT); \
})
#define RGB565_TO_Y_FAST(pixel) \
(((pixel & 0x1f00) >> 5) + (pixel & 0xf8) + ((pixel & 0x7) << 6) + ((pixel & 0xe000) >> 10)) / 4;
#define IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x) \
({ \
__typeof__ (row_ptr) _row_ptr = (row_ptr); \
@ -1148,10 +1192,26 @@ typedef struct find_barcodes_list_lnk_data {
} find_barcodes_list_lnk_data_t;
typedef enum image_hint {
IMAGE_HINT_BILINEAR = 1,
IMAGE_HINT_CENTER = 128
IMAGE_HINT_AREA = 1,
IMAGE_HINT_BILINEAR = 2,
IMAGE_HINT_BICUBIC = 4,
IMAGE_HINT_CENTER = 128,
IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST = 256,
IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST = 512
} image_hint_t;
typedef struct imlib_draw_row_data {
image_t *dst_img; // user
int src_img_bpp; // user
int rgb_channel; // user
int alpha; // user
const uint16_t *color_palette; // user
const uint8_t *alpha_palette; // user
int toggle; // private
void *row_buffer[2]; // private
long smuad_alpha; // private
uint32_t *smuad_alpha_palette; // private
} imlib_draw_row_data_t;
/* Color space functions */
int8_t imlib_rgb565_to_l(uint16_t pixel);
@ -1284,6 +1344,11 @@ void imlib_find_hog(image_t *src, rectangle_t *roi, int cell_size);
// Helper Functions
void imlib_zero(image_t *img, image_t *mask, bool invert);
void imlib_draw_row_setup(imlib_draw_row_data_t *data);
void imlib_draw_row_teardown(imlib_draw_row_data_t *data);
void *imlib_draw_row_get_row_buffer(imlib_draw_row_data_t *data);
void imlib_draw_row_put_row_buffer(imlib_draw_row_data_t *data, void *row_buffer);
void imlib_draw_row(int x_start, int x_end, int y_row, imlib_draw_row_data_t *data);
void imlib_flood_fill_int(image_t *out, image_t *img, int x, int y,
int seed_threshold, int floating_threshold,
flood_fill_call_back_t cb, void *data);
@ -1297,8 +1362,8 @@ void imlib_draw_circle(image_t *img, int cx, int cy, int r, int c, int thickness
void imlib_draw_ellipse(image_t *img, int cx, int cy, int rx, int ry, int rotation, int c, int thickness, bool fill);
void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int c, float scale, int x_spacing, int y_spacing, bool mono_space,
int char_rotation, bool char_hmirror, bool char_vflip, int string_rotation, bool string_hmirror, bool string_hflip);
void imlib_draw_image(image_t *img, image_t *other, int x_off, int y_off, float x_scale, float y_scale, int alpha, image_t *mask,
const uint16_t *color_palette, const uint8_t *alpha_palette, image_hint_t hint);
void imlib_draw_image(image_t *dst_img, image_t *src_img, int dst_x_start, int dst_y_start, float x_scale, float y_scale, rectangle_t *roi,
int rgb_channel, int alpha, const uint16_t *color_palette, const uint8_t *alpha_palette, image_hint_t hint);
void imlib_flood_fill(image_t *img, int x, int y,
float seed_threshold, float floating_threshold,
int c, bool invert, bool clear_background, image_t *mask);

View File

@ -137,8 +137,8 @@ int py_helper_keyword_int(uint n_args, const mp_obj_t *args, uint arg_index,
return default_val;
}
int py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int* value)
bool py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int* value)
{
mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, kw, MP_MAP_LOOKUP);
@ -165,6 +165,20 @@ float py_helper_keyword_float(uint n_args, const mp_obj_t *args, uint arg_index,
return default_val;
}
bool py_helper_keyword_float_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, float *value)
{
mp_map_elem_t *kw_arg = mp_map_lookup(kw_args, kw, MP_MAP_LOOKUP);
if (kw_arg) {
return mp_obj_get_float_maybe(kw_arg->value, value);
} else if (n_args > arg_index) {
return mp_obj_get_float_maybe(args[arg_index], value);
}
return false;
}
void py_helper_keyword_int_array(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int *x, int size)
{

View File

@ -31,10 +31,12 @@ void py_helper_keyword_rectangle_roi(image_t *img, uint n_args, const mp_obj_t *
mp_map_t *kw_args, rectangle_t *r);
int py_helper_keyword_int(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int default_val);
int py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int* value);
bool py_helper_keyword_int_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int* value);
float py_helper_keyword_float(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, float default_val);
bool py_helper_keyword_float_maybe(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, float* value);
void py_helper_keyword_int_array(uint n_args, const mp_obj_t *args, uint arg_index,
mp_map_t *kw_args, mp_obj_t kw, int *x, int size);
void py_helper_keyword_float_array(uint n_args, const mp_obj_t *args, uint arg_index,

View File

@ -1431,11 +1431,11 @@ static mp_obj_t py_image_copy_int(uint n_args, const mp_obj_t *args, mp_map_t *k
float arg_x_scale =
py_helper_keyword_float(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), 1.0f);
PY_ASSERT_TRUE_MSG((0.0f <= arg_x_scale), "Error: 0.0 <= x_scale!");
PY_ASSERT_TRUE_MSG((0.0f <= arg_x_scale), "Error: 0.0 <= x_scale!");
float arg_y_scale =
py_helper_keyword_float(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), 1.0f);
PY_ASSERT_TRUE_MSG((0.0f <= arg_y_scale), "Error: 0.0 <= y_scale!");
PY_ASSERT_TRUE_MSG((0.0f <= arg_y_scale), "Error: 0.0 <= y_scale!");
mp_obj_t copy_to_fb_obj = py_helper_keyword_object(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(mode ? MP_QSTR_copy : MP_QSTR_copy_to_fb));
bool copy_to_fb = false;
@ -1847,87 +1847,79 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_edges_obj, 2, py_image_draw_edge
STATIC mp_obj_t py_image_draw_image(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_helper_arg_to_image_mutable(args[0]);
image_t *arg_other =
py_helper_arg_to_image_mutable(args[1]);
image_t *arg_other = py_helper_arg_to_image_mutable(args[1]);
const mp_obj_t *arg_vec;
uint offset = py_helper_consume_array(n_args, args, 2, 2, &arg_vec);
int arg_cx = mp_obj_get_int(arg_vec[0]);
int arg_cy = mp_obj_get_int(arg_vec[1]);
int arg_x_off = mp_obj_get_int(arg_vec[0]);
int arg_y_off = mp_obj_get_int(arg_vec[1]);
float arg_x_scale =
py_helper_keyword_float(n_args, args, offset + 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), 1.0f);
PY_ASSERT_TRUE_MSG((0.0f <= arg_x_scale), "Error: 0.0 <= x_scale!");
float arg_x_scale = 1.f;
bool got_x_scale = py_helper_keyword_float_maybe(n_args, args, offset + 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_scale), &arg_x_scale);
float arg_y_scale =
py_helper_keyword_float(n_args, args, offset + 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), 1.0f);
PY_ASSERT_TRUE_MSG((0.0f <= arg_y_scale), "Error: 0.0 <= y_scale!");
float arg_y_scale = 1.f;
bool got_y_scale = py_helper_keyword_float_maybe(n_args, args, offset + 1, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_scale), &arg_y_scale);
int arg_alpha =
py_helper_keyword_int(n_args, args, offset + 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_alpha), 256);
PY_ASSERT_TRUE_MSG((0 <= arg_alpha) && (arg_alpha <= 256), "Error: 0 <= alpha <= 256!");
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, offset + 3, kw_args);
rectangle_t arg_roi;
py_helper_keyword_rectangle_roi(arg_other, n_args, args, offset + 2, kw_args, &arg_roi);
int arg_rgb_channel = py_helper_keyword_int(n_args, args, offset + 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rgb_channel), -1);
if ((arg_rgb_channel < -1) || (2 < arg_rgb_channel)) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "-1 <= rgb_channel <= 2!"));
int arg_alpha = py_helper_keyword_int(n_args, args, offset + 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_alpha), 256);
if ((arg_alpha < 0) || (256 < arg_alpha)) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "0 <= alpha <= 256!"));
const uint16_t *color_palette = NULL;
{
int palette;
if (py_helper_keyword_int_maybe(n_args, args, offset + 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_palette), &palette)) {
if (palette == COLOR_PALETTE_RAINBOW) {
color_palette = rainbow_table;
} else if (palette == COLOR_PALETTE_IRONBOW) {
color_palette = ironbow_table;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid pre-defined color palette!"));
}
if (py_helper_keyword_int_maybe(n_args, args, offset + 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_palette), &palette)) {
if (palette == COLOR_PALETTE_RAINBOW) color_palette = rainbow_table;
else if (palette == COLOR_PALETTE_IRONBOW) color_palette = ironbow_table;
else nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid pre-defined color palette!"));
} else {
image_t *arg_color_palette = py_helper_keyword_to_image_mutable_color_palette(n_args, args, offset + 4, kw_args);
image_t *arg_color_palette = py_helper_keyword_to_image_mutable_color_palette(n_args, args, offset + 5, kw_args);
if (arg_color_palette) {
if (arg_color_palette->bpp != IMAGE_BPP_RGB565) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palette must be an RGB565 format image!"));
if ((arg_color_palette->w * arg_color_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palette image must have 256 pixels!"));
color_palette = (uint16_t*)arg_color_palette->data;
if (arg_color_palette->bpp != IMAGE_BPP_RGB565) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palette must be RGB565!"));
if ((arg_color_palette->w * arg_color_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palette must be 256 pixels!"));
color_palette = (uint16_t *) arg_color_palette->data;
}
}
if (color_palette) {
if (arg_other->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Can only specify a color palette when passing a grayscale image!"));
}
}
if (color_palette && arg_img->bpp != IMAGE_BPP_RGB565) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Color palettes must be used with color images!"));
}
const uint8_t *alpha_palette = NULL;
{
image_t *arg_alpha_palette = py_helper_keyword_to_image_mutable_alpha_palette(n_args, args, offset + 5, kw_args);
image_t *arg_alpha_palette = py_helper_keyword_to_image_mutable_alpha_palette(n_args, args, offset + 6, kw_args);
if (arg_alpha_palette) {
if (arg_other->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Can only specify an alpha palette when passing a grayscale image!"));
if (arg_alpha_palette->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette must be an grayscale format image!"));
if ((arg_alpha_palette->w * arg_alpha_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette image must have 256 pixels!"));
if (arg_img->bpp != IMAGE_BPP_GRAYSCALE && arg_img->bpp != IMAGE_BPP_RGB565) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palettes must be used with color images!"));
alpha_palette = (uint8_t*)arg_alpha_palette->data;
if (arg_alpha_palette->bpp != IMAGE_BPP_GRAYSCALE) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette must be GRAYSCALE!"));
if ((arg_alpha_palette->w * arg_alpha_palette->h) != 256) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Alpha palette must be 256 pixels!"));
alpha_palette = (uint8_t *) arg_alpha_palette->data;
}
}
image_hint_t hint =
py_helper_keyword_int(n_args, args, offset + 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_hint), 0);
image_hint_t hint = py_helper_keyword_int(n_args, args, offset + 7, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_hint), 0);
if (hint && arg_msk) {
// This check is only performed if there is a hint for backwards compatiblity with old draw image where dimesions were not enforced.
if (arg_msk->w != arg_other->w || arg_msk->h != arg_other->h) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Mask must have same dimensions as image"));
}
}
int arg_x_size;
bool got_x_size = py_helper_keyword_int_maybe(n_args, args, offset + 8, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_x_size), &arg_x_size);
imlib_draw_image(arg_img, arg_other, arg_cx, arg_cy, arg_x_scale, arg_y_scale, arg_alpha, arg_msk, color_palette, alpha_palette, hint);
int arg_y_size;
bool got_y_size = py_helper_keyword_int_maybe(n_args, args, offset + 9, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_y_size), &arg_y_size);
if (got_x_scale && got_x_size) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Choose either x_scale or x_size not both!"));
if (got_y_scale && got_y_size) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Choose either y_scale or y_size not both!"));
if (got_x_size) arg_x_scale = arg_x_size / ((float) arg_other->w);
if (got_y_size) arg_y_scale = arg_y_size / ((float) arg_other->h);
if ((!got_x_scale) && (!got_x_size) && got_y_size) arg_x_scale = arg_y_scale;
if ((!got_y_scale) && (!got_y_size) && got_x_size) arg_y_scale = arg_x_scale;
fb_alloc_mark();
imlib_draw_image(arg_img, arg_other, arg_x_off, arg_y_off, arg_x_scale, arg_y_scale, &arg_roi,
arg_rgb_channel, arg_alpha, color_palette, alpha_palette, hint);
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_draw_image_obj, 3, py_image_draw_image);
@ -7506,6 +7498,12 @@ int py_image_descriptor_from_roi(image_t *img, const char *path, rectangle_t *ro
static const mp_rom_map_elem_t globals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_image)},
{MP_ROM_QSTR(MP_QSTR_AREA), MP_ROM_INT(IMAGE_HINT_AREA)},
{MP_ROM_QSTR(MP_QSTR_BILINEAR), MP_ROM_INT(IMAGE_HINT_BILINEAR)},
{MP_ROM_QSTR(MP_QSTR_BICUBIC), MP_ROM_INT(IMAGE_HINT_BICUBIC)},
{MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(IMAGE_HINT_CENTER)},
{MP_ROM_QSTR(MP_QSTR_EXTRACT_RGB_CHANNEL_FIRST), MP_ROM_INT(IMAGE_HINT_EXTRACT_RGB_CHANNEL_FIRST)},
{MP_ROM_QSTR(MP_QSTR_APPLY_COLOR_PALETTE_FIRST), MP_ROM_INT(IMAGE_HINT_APPLY_COLOR_PALETTE_FIRST)},
#ifdef IMLIB_FIND_TEMPLATE
{MP_ROM_QSTR(MP_QSTR_SEARCH_EX), MP_ROM_INT(SEARCH_EX)},
{MP_ROM_QSTR(MP_QSTR_SEARCH_DS), MP_ROM_INT(SEARCH_DS)},
@ -7540,8 +7538,6 @@ static const mp_rom_map_elem_t globals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_CODE93), MP_ROM_INT(BARCODE_CODE93)},
{MP_ROM_QSTR(MP_QSTR_CODE128), MP_ROM_INT(BARCODE_CODE128)},
#endif
{MP_ROM_QSTR(MP_QSTR_IMAGE_HINT_BILINEAR),MP_ROM_INT(IMAGE_HINT_BILINEAR)},
{MP_ROM_QSTR(MP_QSTR_IMAGE_HINT_CENTER), MP_ROM_INT(IMAGE_HINT_CENTER)},
{MP_ROM_QSTR(MP_QSTR_ImageWriter), MP_ROM_PTR(&py_image_imagewriter_obj)},
{MP_ROM_QSTR(MP_QSTR_ImageReader), MP_ROM_PTR(&py_image_imagereader_obj)},
{MP_ROM_QSTR(MP_QSTR_binary_to_grayscale), MP_ROM_PTR(&py_image_binary_to_grayscale_obj)},

View File

@ -552,11 +552,20 @@ Q(draw_edges)
Q(draw_image)
// duplicate Q(x_scale)
// duplicate Q(y_scale)
// duplicate Q(roi)
// duplicate Q(rgb_channel)
Q(alpha)
// duplicate Q(mask)
// duplicate Q(color_palette)
// duplicate Q(alpha_palette)
Q(hint)
Q(IMAGE_HINT_BILINEAR)
Q(IMAGE_HINT_CENTER)
Q(AREA)
Q(BILINEAR)
Q(BICUBIC)
Q(CENTER)
Q(EXTRACT_RGB_CHANNEL_FIRST)
Q(APPLY_COLOR_PALETTE_FIRST)
Q(x_size)
Q(y_size)
// Draw Keypoints
Q(draw_keypoints)