{"id":1059,"date":"2021-07-30T16:25:58","date_gmt":"2021-07-30T09:25:58","guid":{"rendered":"https:\/\/bigdolphin.com.vn\/?p=1059"},"modified":"2024-03-26T15:25:38","modified_gmt":"2024-03-26T08:25:38","slug":"playing-with-maixduino-detecting-barcode-qr-code-and-airtag-using-micropython","status":"publish","type":"post","link":"https:\/\/bigdolphin.com.vn\/?p=1059","title":{"rendered":"Playing with Maixduino: detecting barcode, QR code and AprilTag using micropython"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">1. Prepare<\/h3>\n\n\n\n<ul><li>Maixduino with customized firmware<\/li><li>Barcode, QR code and AprilTag code for testing<\/li><\/ul>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-layout-1 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"231\" height=\"231\" src=\"https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-36.png\" alt=\"\" class=\"wp-image-1096\" srcset=\"https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-36.png 231w, https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-36-150x150.png 150w\" sizes=\"(max-width: 231px) 100vw, 231px\" \/><figcaption><strong>EAN-8 barcode<\/strong><\/figcaption><\/figure><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"231\" height=\"231\" src=\"https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-37.png\" alt=\"\" class=\"wp-image-1097\" srcset=\"https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-37.png 231w, https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-37-150x150.png 150w\" sizes=\"(max-width: 231px) 100vw, 231px\" \/><figcaption><strong>QR code<\/strong><\/figcaption><\/figure><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"178\" height=\"231\" src=\"https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-38.png\" alt=\"\" class=\"wp-image-1098\"\/><figcaption><strong>TAG36H11 AprilTag<\/strong><\/figcaption><\/figure><\/div>\n<\/div>\n<\/div>\n\n\n\n<p>All types of codes above can be generated from built-in tool of MaixPy IDE. Go to &#8220;Tools -&gt; Machine Vision&#8221; to select generator you need.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"601\" src=\"https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-39-1024x601.png\" alt=\"\" class=\"wp-image-1104\" srcset=\"https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-39-1024x601.png 1024w, https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-39-300x176.png 300w, https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-39-768x451.png 768w, https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/image-39.png 1308w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption>Generate Bar code, QR code and AprilTag with MaixPy IDE.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">2. Barcode detection<\/h3>\n\n\n\n<p>Barcode detection is a built-in function inside OMV module of Micropython. This function requires medium resolution image to get best results, it should be 640 by 40\/80\/160 window.  Calling function is <span class=\"has-inline-color has-gtb-color-4-color\"><em><strong>find_barcodes([roi])<\/strong><\/em> <\/span>where roi is region-of-interest rectangle tuple (x,y,w,h). If roi is not specified, it is equal to whole image. This function does not support compressed image or bayer image. Return value is barcode class object. If there are many barcodes inside the roi, return value is array of objects. Barcode class object has functions as in table below.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Method name<\/th><th>Features<\/th><\/tr><\/thead><tbody><tr><td>barcode.corners()<\/td><td>Returns a list of four tuples (x, y) consisting of the four corners of the object. The four corners are usually returned in clockwise order starting from the upper left corner.<\/td><\/tr><tr><td>barcode.rect()<\/td><td>Return a rectangular tuple (x, y, w, h), used in other image methods such as image.draw_rectangle of the bounding box of the data matrix.<\/td><\/tr><tr><td>barcode.x()<\/td><td>Returns the x coordinate of the bounding box of the barcode (int)<\/td><\/tr><tr><td>barcode.y()<\/td><td>Returns the y coordinate (int) of the bounding box of the barcode.<\/td><\/tr><tr><td>barcode.w()<\/td><td>Returns the w width of the bounding box of the barcode (int)<\/td><\/tr><tr><td>barcode.h()<\/td><td>Returns the h height (int) of the bounding box of the barcode.<\/td><\/tr><tr><td>barcode.payload()<\/td><td>Returns the string of the payload of the barcode. Example: Quantity.<\/td><\/tr><tr><td>barcode.type()<\/td><td>Returns the enumeration type of the barcode (int)<\/td><\/tr><tr><td>barcode.rotation()<\/td><td>Returns the curl of the barcode in radians (floating point number)<\/td><\/tr><tr><td>barcode.quality()<\/td><td>Returns the number of times the barcode was detected in the image (int)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python line-numbers\">snapshot = sensor.snapshot()\ncode = snapshot.find_barcodes()\nfor i in code:\n    code_text = i.payload()\n    print(code_text)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. QR Code detection<\/h3>\n\n\n\n<p>Like Bar code, QR code detection is also a built-in function inside OMV module of Micropython. This function can work well with low resolution image. Calling function is <span class=\"has-inline-color has-gtb-color-4-color\"><em><strong>find_qrcodes([roi])<\/strong><\/em> <\/span>where roi is region-of-interest rectangle tuple (x,y,w,h). If roi is not specified, it is equal to whole image. This function does not support compressed image or bayer image. Return value is QR code class object. If there are many QR codes inside the roi, return value is array of objects. QR code class object has functions as in table below.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Method name<\/th><th>Features<\/th><\/tr><\/thead><tbody><tr><td>qrcode.corners()<\/td><td>Returns a list of four tuples (x, y) consisting of the four corners of the object. The four corners are usually returned in clockwise order starting from the upper left corner.<\/td><\/tr><tr><td>qrcode.rect()<\/td><td>Returns a rectangular tuple (x, y, w, h), used in other image methods such as image.draw_rectangle of the bounding box of the QR code.<\/td><\/tr><tr><td>qrcode.x()<\/td><td>Returns the x coordinate of the bounding box of the QR code (int)<\/td><\/tr><tr><td>qrcode.y()<\/td><td>Returns the y coordinate (int) of the bounding box of the QR code.<\/td><\/tr><tr><td>qrcode.w()<\/td><td>Returns the w coordinate (int) of the bounding box of the QR code.<\/td><\/tr><tr><td>qrcode.h()<\/td><td>Returns the h coordinate (int) of the bounding box of the QR code.<\/td><\/tr><tr><td>qrcode.payload()<\/td><td>Returns the string of the QR code payload, such as URL.<\/td><\/tr><tr><td>qrcode.version()<\/td><td>Returns the version number (int) of the QR code.<\/td><\/tr><tr><td>qrcode.ecc_level()<\/td><td>Returns the ECC level of the QR code (int).<\/td><\/tr><tr><td>qrcode.data_type()<\/td><td>Returns the data type of the QR code.<\/td><\/tr><tr><td>qrcode.eci()<\/td><td>Returns the ECI of the QR code. ECI stores the code of the data bytes stored in the QR code. If you want to process a QR code that contains more than standard ASCII text, you need to check this value.<\/td><\/tr><tr><td>qrcode.is_numeric()<\/td><td>If the data type of the QR code is digital, it returns True<\/td><\/tr><tr><td>qrcode.is_alphanumeric()<\/td><td>If the data type of the QR code is alphanumeric, it returns True.<\/td><\/tr><tr><td>qrcode.is_binary()<\/td><td>If the data type of the QR code is binary, it returns True<\/td><\/tr><tr><td>qrcode.is_kanji()<\/td><td>If the data type of the QR code is Kanji, it returns True<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python line-numbers\">_target_rect = [(224-120)\/\/2, (224-120)\/\/2, 120, 120]\nsnapshot = sensor.snapshot()\ncode = snapshot.find_qrcodes(_target_rect)\nfor i in code:\n    code_text = i.payload()\n    print(code_text)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. AprilTag<\/h3>\n\n\n\n<p><strong><a href=\"https:\/\/april.eecs.umich.edu\/software\/apriltag\" target=\"_blank\" rel=\"noreferrer noopener\">AprilTag<\/a><\/strong> is a visual fiducial system, useful for a wide variety of tasks including augmented reality, robotics, and camera calibration. Targets can be created from an ordinary printer, and the AprilTag detection software computes the precise 3D position, orientation, and identity of the tags relative to the camera. The AprilTag library is implemented in C with no external dependencies. It is designed to be easily included in other applications, as well as be portable to embedded devices. Real-time performance can be achieved even on cell-phone grade processors.<\/p>\n\n\n\n<p><strong>The most advantage of apriltag is robust to lighting conditions and view angle.<\/strong> Maixpy IDE has built-in tool to generate this tag. <\/p>\n\n\n\n<p>In Micropython, apriltag detection is implemented inside OMV module. Calling function is <span class=\"has-inline-color has-gtb-color-4-color\"><em><strong>find_apriltags([roi])<\/strong><\/em> <\/span>where roi is region-of-interest rectangle tuple (x,y,w,h). If roi is not specified, it is equal to whole image. A big issue of this function in Micropython is it allocs much RAM that usually causes &#8220;Out of momery&#8221; issue. Therefore, the ROI size should be 32&#215;32 maximum, the best size is 28&#215;28. This function does not support compressed image or bayer image. Return value is AprilTag code class object. If there are many AprilTag codes inside the roi, return value is array of objects. AprilTag code class object has functions as in table below.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Method name<\/th><th>Features<\/th><\/tr><\/thead><tbody><tr><td>apriltag.corners()<\/td><td>Returns a list of four tuples (x, y) consisting of the four corners of the object.<\/td><\/tr><tr><td>apriltag.rect()<\/td><td>Returns a rectangular tuple (x, y, w, h), used in other image methods such as image.draw_rectangle of AprilTag bounding box<\/td><\/tr><tr><td>apriltag.x()<\/td><td>Returns the x coordinate (int) of the AprilTag bounding box.<\/td><\/tr><tr><td>apriltag.y()<\/td><td>Returns the y coordinate (int) of the bounding box of AprilTag.<\/td><\/tr><tr><td>apriltag.w()<\/td><td>Returns the w coordinate (int) of the bounding box of AprilTag.<\/td><\/tr><tr><td>apriltag.h()<\/td><td>Returns the h coordinate (int) of the bounding box of AprilTag.<\/td><\/tr><tr><td>apriltag.id()<\/td><td>Returns the numeric ID of AprilTag.<\/td><\/tr><tr><td>apriltag.family()<\/td><td>Return to AprilTag&#8217;s digital home.<\/td><\/tr><tr><td>apriltag.cx()<\/td><td>Returns the center x position (int) of AprilTag.<\/td><\/tr><tr><td>apriltag.cy()<\/td><td>Returns the center y position (int) of AprilTag.<\/td><\/tr><tr><td>apriltag.rotation()<\/td><td>Returns the curl of AprilTag in radians (int).<\/td><\/tr><tr><td>apriltag.decision_margin()<\/td><td>Returns the color saturation of AprilTag matching (value 0.0-1.0), where 1.0 is the best.<\/td><\/tr><tr><td>apriltag.hamming()<\/td><td>Returns the acceptable digital error value of AprilTag.<\/td><\/tr><tr><td>apriltag.goodness()<\/td><td>Returns the color saturation of the AprilTag image (value 0.0-1.0), where 1.0 is the best.<\/td><\/tr><tr><td>apriltag.x_translation()<\/td><td>Returns the transformation in the x direction from the camera. The unit of the distance is unknown.<\/td><\/tr><tr><td>apriltag.y_translation()<\/td><td>Returns the transformation in the y direction from the camera. The unit of the distance is unknown.<\/td><\/tr><tr><td>apriltag.z_translation()<\/td><td>Returns the transformation in the z direction from the camera. The unit of the distance is unknown.<\/td><\/tr><tr><td>apriltag.x_rotation()<\/td><td>Returns the rotation of AprilTag on the X plane in radians. Example: Looking at AprilTag, move the camera from left to right.<\/td><\/tr><tr><td>apriltag.y_rotation()<\/td><td>Returns the rotation of AprilTag in radians on the Y plane. Example: Looking at AprilTag, move the camera from top to bottom.<\/td><\/tr><tr><td>apriltag.z_rotation()<\/td><td>Returns the rotation of AprilTag in radians on the Z plane. Example: Look at AprilTag and rotate the camera.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python line-numbers\">_target_rect = [(224-28)\/\/2, (224-28)\/\/2, 28, 28]\nsnapshot = sensor.snapshot()\ncode = snapshot.find_apriltags(_target_rect)\nfor i in code:\n    code_text = str(i.id())\n    print(code_text)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">5. Full script and test<\/h3>\n\n\n\n<p>The script below will detect all types of codes (Bar code, QR code and AprilTag) with a LvGl GUI on LCD screen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python line-numbers\"># Notice: LvGl must be enabled in firmware\nimport sensor, image, time, lcd, gc, micropython\nimport lvgl as lv\nimport lvgl_helper as lv_h\n\nfrom fpioa_manager import fm\nfrom board import board_info\nfrom machine import Timer\n\n###################################\nprint('\\n-----------------------------')\n# Check frequencies and overclock\nimport gc, micropython\nfrom Maix import freq, GPIO, utils\nfrom machine import reset\n\ncpu_frq, kpu_frq=freq.get()\nprint(\"\\nCPU Frq = %d MHz\" % (cpu_frq))\nprint(\"KPU Frq = %d MHz\" % (kpu_frq))\n\nif cpu_frq != 546 or kpu_frq != 450:\n    print(\"Removing old frequency...\")\n    os.remove(\"freq.conf\")\n    print(\"Overclocking CPU to 546 MHz and KPU to 450 MHz...\")\n    # kpu frequency is pll1\/kpu_div\n    freq.set (cpu=546, pll1=450, kpu_div=1)\n\ngc.enable()\ngc.collect()\ngc.threshold(gc.mem_free() \/\/ 4 + gc.mem_alloc())\nmicropython.mem_info()\nmem_heap = utils.gc_heap_size()\nheap_free = utils.heap_free()\nprint(\"Heap size: %d bytes, free: %d bytes\" % (mem_heap,heap_free))\nif mem_heap != 393216:\n    print(\"Decreasing GC heap size...\")\n    utils.gc_heap_size(393216)\n    reset()\nprint('-----------------------------')\n ###################################\n\n# Register GPIO\nfm.register(board_info.LED_R, fm.fpioa.GPIO0)\nfm.register(board_info.LED_G, fm.fpioa.GPIO1)\nfm.register(board_info.LED_B, fm.fpioa.GPIO2)\nled_r=GPIO(GPIO.GPIO0, GPIO.OUT)\nled_g=GPIO(GPIO.GPIO1, GPIO.OUT)\nled_b=GPIO(GPIO.GPIO2, GPIO.OUT)\n\n# Function to control RGB led\ndef led_rgb(r,g,b):\n    led_r.value(r)\n    led_g.value(g)\n    led_b.value(b)\n\n# Function to init camera sensor\n# Maixduino can also work with OV5640\ndef init_sensor():\n    sensor.reset()\n    sensor.set_pixformat(sensor.RGB565)\n    sensor.set_framesize(sensor.QVGA)\n    # set to 224x224 input\n    sensor.set_windowing((224, 224))\n    sensor.set_vflip(0)\n    sensor.set_hmirror(0)\n    sensor.run(1)\n    sensor.skip_frames(30)\n\n# Camera frame speed\ncamera_fps = 30\n# LvGl render interval\ntimer_period = 1000\/\/camera_fps\n# Timer counting flag for other functions\ntimer_flag = 0\ndef on_timer(timer):\n    global timer_flag\n    global timer_period\n    timer_flag = timer_flag + 1\n    # Notice to LvGL that timer_period passed\n    lv.tick_inc(timer_period)\n\nled_rgb(0,1,1)\nclock = time.clock()\n\n# Init LCD\nlcd.init(freq=15000000)\nlcd.rotation(0)\nlcd.clear()\n# Init LvGl\nlv.init()\ndisp_buf1 = lv.disp_buf_t()\nbuf1_1 = bytearray(320*10)\nlv.disp_buf_init(disp_buf1,buf1_1, None, len(buf1_1)\/\/4)\ndisp_drv = lv.disp_drv_t()\nlv.disp_drv_init(disp_drv)\ndisp_drv.buffer = disp_buf1\ndisp_drv.flush_cb = lv_h.flush\ndisp_drv.hor_res = 320\ndisp_drv.ver_res = 240\nlv.disp_drv_register(disp_drv)\nscr = lv.obj()\n# Set background color\nscr_style = lv.style_t(lv.style_plain)\nscr_style.body.main_color = lv.color_hex(0)\nscr_style.body.grad_color = lv.color_hex(0)\nscr.set_style(scr_style)\n\ninit_sensor()\nled_rgb(1,0,1)\n\n# Add elements to screen\n# Capture button\nbtn_capture = lv.btn(scr)\nbtn_capture.set_size(100,50)\nbtn_capture.align(lv.scr_act(), lv.ALIGN.IN_BOTTOM_MID, 0, 0)\nlabel_capture = lv.label(btn_capture)\nlabel_capture.set_text(\"Capture\")\nlabel_capture.set_size(20,20)\n# Left button\nbtn_left = lv.btn(scr)\nbtn_left.set_size(50,50)\nbtn_left.align(lv.scr_act(), lv.ALIGN.IN_BOTTOM_LEFT, 0, 0)\nlabel_left = lv.label(btn_left)\nlabel_left.set_text(\"&lt;&lt;\")\nlabel_left.set_size(50,50)\n# Right button\nbtn_right = lv.btn(scr)\nbtn_right.set_size(50,50)\nbtn_right.align(lv.scr_act(), lv.ALIGN.IN_BOTTOM_RIGHT, 0, 0)\nlabel_right = lv.label(btn_right)\nlabel_right.set_text(\"&gt;&gt;\")\nlabel_right.set_size(50,50)\n# Image frame\nvideo = lv.img(scr)\nvideo.align(scr, lv.ALIGN.IN_TOP_LEFT, (320 - (240-55))\/\/2, 0)\n# Label\nlb_info = lv.label(scr)\nlb_info.set_long_mode(lv.label.LONG.SROLL)\nlb_info.set_width(200)\nlb_info.align(None, lv.ALIGN.IN_BOTTOM_MID, 0, -60)\nlb_info.set_align(lv.label.ALIGN.CENTER)\n# Enable re-coloring by commands in the text\nlb_info.set_recolor(True)\nlb_style = lv.style_t(lv.style_plain)\nlb_style.text.color = lv.color_hex(0xffffff)\nlb_info.set_style(lv.label.STYLE.MAIN,lb_style)\nlb_info.set_text(\"Waiting for code...\")\n# Reload screen\nlv.scr_load(scr)\n# Activate timer\ntimer = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PERIODIC, period=timer_period, unit=Timer.UNIT_MS, callback=on_timer, arg=None)\n###################################\n# Main task\nled_state = 0\n# Target rect 120x120 center of QVGA.\n_target_rect = [(224-120)\/\/2, (224-120)\/\/2, 120, 120]\ncode = []\ncode_type = 0\nwhile True:\n    clock.tick()\n    # Capture camera\n    snapshot = sensor.snapshot()\n    # Get real FPS\n    fps =clock.fps()\n    lcd.draw_string(4,2 ,(\"%2.1ffps\\r\" %(fps)),lcd.WHITE,lcd.BLACK)\n    try:\n        # Rotate image if needed\n        # snapshot.set(hmirror=True, vflip=False, transpose=True)\n        # Get data of target area\n        target = snapshot.copy(_target_rect)\n        # Convert to gray\n        target = target.to_grayscale()\n        # Find BAR code\n        # find_barcodes requires high resolution then must use full snapshot\n        code = snapshot.find_barcodes()\n        if len(code) &gt; 0:\n            lcd.draw_string(4,22 ,\"BARCODE\\r\",lcd.WHITE,lcd.BLACK)\n            code_type = 1\n        else:\n            # Find QR code\n            # find_qrcodes can use small target area to save RAM\n            code = target.find_qrcodes()\n            if len(code) &gt; 0:\n                lcd.draw_string(4,22 ,\"QR CODE\\r\",lcd.WHITE,lcd.BLACK)\n                code_type = 2\n            else:\n                # Resize target to 28x28 for AprilTag\n                # find_apriltags must use area 32x32 maximum to have enough RAM\n                target = target.resize(28,28)\n                # Find ArilTag code\n                code = target.find_apriltags()\n                if len(code) &gt; 0:\n                    lcd.draw_string(4,22 ,\"April  \\r\",lcd.WHITE,lcd.BLACK)\n                    code_type = 3\n                else:\n                    lcd.draw_string(4,22 ,\"NONE   \\r\",lcd.WHITE,lcd.BLACK)\n                    code_type = 0\n        # Draw target rectangle\n        snapshot.draw_rectangle(_target_rect,color=(0,255,0),thickness=5)\n        # Resize to fit into image frame on screen\n        snapshot = snapshot.resize(185,185)\n        lcd.draw_string(256,2 ,\"-----\\r\",lcd.WHITE,lcd.BLACK)\n    except Exception as e:\n        print(\"[ERROR] Exception: %s\" % (e))\n        lcd.draw_string(254,2 ,\"ERROR\\r\",lcd.WHITE,lcd.BLACK)\n        gc.collect()\n    for i in code:\n        code_text = \"\"\n        if code_type &lt; 3:\n            code_text = i.payload()\n        else:\n            code_text = str(i.id())\n        lb_style.text.color = lv.color_hex(0x00ff00)\n        lb_info.set_style(lv.label.STYLE.MAIN,lb_style)\n        lb_info.set_text(code_text)\n    # Set frame data to image element\n    video_data = snapshot.to_bytes()\n    video_dsc = lv.img_dsc_t({\n        'header':{\n            'always_zero': 0,\n            'w':snapshot.width(),\n            'h':snapshot.height(),\n            'cf':lv.img.CF.TRUE_COLOR\n        },\n        'data_size': len(video_data),\n        'data': video_data\n    })\n    video.set_src(video_dsc)\n    lv.task_handler()\n    # Check timer event\n    if timer_flag &gt; (500\/\/timer_period):\n        timer_flag = 0\n        led_state = ~led_state\n        led_rgb(1,1,led_state)<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-video\"><video src=\"https:\/\/bigdolphin.com.vn\/wp-content\/uploads\/2021\/07\/mai_qr.mp4\"><\/video><\/figure>\n\n\n\n<p>Full script can be downloaded from <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/bigdolphin\/maixduino\" target=\"_blank\">https:\/\/github.com\/bigdolphin\/maixduino<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A GUI app on Maixduino to read BAR code, QR code and AprilTag code using Micropython.<\/p>\n","protected":false},"author":2,"featured_media":1109,"comment_status":"open","ping_status":"open","sticky":false,"template":"single-with-sidebar","format":"standard","meta":{"gtb_hide_title":false,"gtb_wrap_title":false,"gtb_class_title":"","gtb_remove_headerfooter":false,"footnotes":""},"categories":[10],"tags":[47,46,31,30,32,45],"_links":{"self":[{"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=\/wp\/v2\/posts\/1059"}],"collection":[{"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1059"}],"version-history":[{"count":10,"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=\/wp\/v2\/posts\/1059\/revisions"}],"predecessor-version":[{"id":1112,"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=\/wp\/v2\/posts\/1059\/revisions\/1112"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=\/wp\/v2\/media\/1109"}],"wp:attachment":[{"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1059"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1059"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bigdolphin.com.vn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1059"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}