diff --git a/docs/doc/en/README.md b/docs/doc/en/README.md index 0ad7179d..c6e31117 100644 --- a/docs/doc/en/README.md +++ b/docs/doc/en/README.md @@ -30,6 +30,8 @@ Purchase the MaixCAM! Note that currently only the MaixCAM development board is supported. Other development boards with the same chip are not supported, including Sipeed's development boards with the same chip. Please be careful not to purchase the wrong board, which could result in unnecessary waste of time and money. diff --git a/docs/doc/en/basic/auto_start.md b/docs/doc/en/basic/auto_start.md new file mode 100644 index 00000000..af5ef903 --- /dev/null +++ b/docs/doc/en/basic/auto_start.md @@ -0,0 +1,25 @@ +--- +title: MaixPy/MaixCAM Application Auto-Start at Boot +--- + +Packaged applications can be set to automatically start when the device boots up, bypassing the application menu and directly launching the specified application. + +## Method One for Setting Application Auto-Start + +First, package and install the application, then go to `Settings -> Auto-Start` on your device to select the application you want to auto-start. To cancel auto-start, you can also adjust it here. + +## Method Two for Setting Application Auto-Start + +You can also modify the `/maixapp/auto_start.txt` file in your device to set it up. For methods on file transfer, refer to the previous documentation. +* First, determine the `id` of the application you want to set. This is set when you package the application; if it's not an application you packaged yourself, you can install it on the device and check the folder names under the device's `/maixapp/apps/` directory, which are the application names (or you can download and check the device's `/maixapp/apps/app.info` file, where the application `id` is indicated inside the `[]` brackets). +* Then write the `id` into the `/maixapp/auto_start.txt` file. (You can create the file locally on your computer, and then transfer it to the device using `MaixVision`.) +* To cancel, delete the `/maixapp/auto_start.txt` file on the device. + +## Other Methods + +For MaixCAM, since the underlying system is Linux, if you are familiar with Linux, you can edit the startup scripts in `/etc/rc.local` or `/etc/init.d`. + +However, it is important to note that this method may cause the application to continue running when MaixVision connects, thereby occupying resources (such as the screen and camera) which might prevent MaixVision from running programs normally. The first two methods allow MaixVision to terminate the program upon connection to run its own programs. + +Thus, this method is more suitable for running background processes that do not occupy screen and camera resources. Generally, if you are not familiar with Linux, it is not recommended to use this method. + diff --git a/docs/doc/en/sidebar.yaml b/docs/doc/en/sidebar.yaml index 63fadeec..c3ca8cc2 100644 --- a/docs/doc/en/sidebar.yaml +++ b/docs/doc/en/sidebar.yaml @@ -23,6 +23,8 @@ items: label: Add python packages - file: basic/app.md label: Apps development + - file: basic/auto_start.md + label: Auto start - label: Basic images and algorithms items: @@ -32,6 +34,8 @@ items: label: Camera uses - file: vision/image_ops.md label: Image control + - file: vision/touchsreen.md + label: Touch screen - file: vision/find_blobs.md label: Finding color blocks - file: vision/line_tracking.md diff --git a/docs/doc/en/source_code/build.md b/docs/doc/en/source_code/build.md index 02283ee2..a1c91a40 100644 --- a/docs/doc/en/source_code/build.md +++ b/docs/doc/en/source_code/build.md @@ -19,10 +19,10 @@ cd ~/maix git clone https://github.com/sipeed/MaixCDK ``` -Then, you need to set the environment variable MAIXCAK_PATH to specify the path to MaixCDK, which can be added in ~/.bashrc or ~/.zshrc (depending on your shell): +Then, you need to set the environment variable MAIXCDK_PATH to specify the path to MaixCDK, which can be added in ~/.bashrc or ~/.zshrc (depending on your shell): ```shell -export MAIXCAK_PATH=~/maix/MaixCDK +export MAIXCDK_PATH=~/maix/MaixCDK ``` Only after successfully setting the environment variable can MaixPy locate the MaixCDK source code. diff --git a/docs/doc/en/vision/touchscreen.md b/docs/doc/en/vision/touchscreen.md new file mode 100644 index 00000000..bbf68140 --- /dev/null +++ b/docs/doc/en/vision/touchscreen.md @@ -0,0 +1,105 @@ +--- +title: MaixPy / MaixCAM Touchscreen Usage Guide +--- + +## Introduction + +MaixCAM comes equipped with a touchscreen, which, when used in conjunction with applications, can facilitate numerous engaging functionalities. We can utilize APIs to detect touch interactions on the touchscreen. + +## Reading Touch Input with MaixPy + +MaixPy offers a straightforward `maix.touchscreen.TouchScreen` class for reading touch inputs. Here's an example: + +```python +from maix import touchscreen, app, time + +ts = touchscreen.TouchScreen() + +pressed_already = False +last_x = 0 +last_y = 0 +last_pressed = False +while not app.need_exit(): + x, y, pressed = ts.read() + if x != last_x or y != last_y or pressed != last_pressed: + print(x, y, pressed) + last_x = x + last_y = y + last_pressed = pressed + if pressed: + pressed_already = True + else: + if pressed_already: + print(f"clicked, x: {x}, y: {y}") + pressed_already = False + time.sleep_ms(1) # sleep some time to free some CPU usage +``` + +## Interactivity with the Screen + +Integrating the screen can enable various interactive user experiences. More examples can be found in the [MaixPy/examples/vision/touchscreen](https://github.com/sipeed/MaixPy) directory. + +As previously described, to display content on the screen, typically, a `maix.image.Image` object is created and displayed using `disp.show(img)`. Implementing a button is as simple as drawing one on the image and then detecting touches within its area, ensuring that the image's dimensions match those of the screen: + +```python +from maix import touchscreen, app, time, display, image + +ts = touchscreen.TouchScreen() +disp = display.Display() + +img = image.Image(disp.width(), disp.height()) + +# draw exit button +exit_label = "< Exit" +size = image.string_size(exit_label) +exit_btn_pos = [0, 0, 8*2 + size.width(), 12 * 2 + size.height()] +img.draw_string(8, 12, exit_label, image.COLOR_WHITE) +img.draw_rect(exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3], image.COLOR_WHITE, 2) + +def is_in_button(x, y, btn_pos): + return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] + +while not app.need_exit(): + x, y, pressed = ts.read() + if is_in_button(x, y, exit_btn_pos): + app.set_exit_flag(True) + img.draw_circle(x, y, 1, image.Color.from_rgb(255, 255, 255), 2) + disp.show(img) +``` + +## Handling Different Screen and Image Sizes + +In the example above, the `img` matches the screen size. If your `img` and screen sizes differ (e.g., using `img = image.Image(240, 240)` on a `640x480` screen), the default behavior of `disp.show(img)` is `image.Fit.FIT_CONTAIN`, which scales the image to `480x480` and fills the sides with black. If a button is drawn on the `240x240` image, such as at coordinates `(0, 0, 60, 40)`, the button will also be scaled up. Thus, the coordinates for touch detection should be adjusted to `((640 - 480) / 2, 0, 480/240*60, 480/240*40)`, which translates to `(80, 0, 120, 80)`. + +For convenience in scaling images and quickly calculating the positions and sizes of points or rectangles in the scaled image, the `image.resize_map_pos` function is provided: + +```python +from maix import touchscreen, app, time, display, image + +ts = touchscreen.TouchScreen() +disp = display.Display() + +img = image.Image(240, 240) +img.draw_rect(0, 0, img.width(), img.height(), image.COLOR_WHITE) + +# draw exit button +exit_label = "< Exit" +size = image.string_size(exit_label) +exit_btn_pos = [0, 0, 8*2 + size.width(), 12 * 2 + size.height()] +img.draw_string(8, 12, exit_label, image.COLOR_WHITE) +img.draw_rect(exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3], image.COLOR_WHITE, 2) +# 图像按键坐标映射到屏幕上的坐标 +exit_btn_disp_pos = image.resize_map_pos(img.width(), img.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3]) + +def is_in_button(x, y, btn_pos): + return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] + +while not app.need_exit(): + x, y, pressed = ts.read() + if is_in_button(x, y, exit_btn_disp_pos): + app.set_exit_flag(True) + # 屏幕的坐标映射回图像上对应的坐标,然后在图像上画点 + x, y = image.resize_map_pos_reverse(img.width(), img.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, x, y) + img.draw_circle(x, y, 1, image.Color.from_rgb(255, 255, 255), 2) + disp.show(img, fit=image.Fit.FIT_CONTAIN) +``` \ No newline at end of file diff --git a/docs/doc/zh/README.md b/docs/doc/zh/README.md index e550190f..cdaf3b58 100644 --- a/docs/doc/zh/README.md +++ b/docs/doc/zh/README.md @@ -31,6 +31,9 @@ title: MaixPy 快速开始 **建议购买带 `TF 卡`、`摄像头`、`2.3寸触摸屏`、`外壳`、`Type-C 数据线`、 `Type-C一转二小板`、`4P串口座子+线`的套餐**,方便后续使用和开发,**后面的教程都默认你已经有了这些配件**(包括屏幕)。 +**强烈建议买带屏幕的套餐,会大大提升开发体验**,如果你实际部署到生产环境不需要屏幕,可以先用带屏幕的入门和开发,最后再去掉屏幕或者购买不带屏幕的量产。 + + 如果你没有购买 TF 卡,则你需要**自备**一个 **TF 读卡器**用来烧录系统。 >! 注意,目前只支持 MaixCAM 开发板,其它同型号芯片的开发板均不支持,包括 Sipeed 的同型号芯片开发板,请注意不要买错造成不必要的时间和金钱浪费。 diff --git a/docs/doc/zh/basic/auto_start.md b/docs/doc/zh/basic/auto_start.md new file mode 100644 index 00000000..47f62121 --- /dev/null +++ b/docs/doc/zh/basic/auto_start.md @@ -0,0 +1,31 @@ +--- +title: MaixPy/MaixCAM 应用开机自启 +--- + +打包安装好的应用可以设置开机自动启动,这样开机就不会显示应用菜单,直接进入指定的应用。 + +## 设置应用开机自启方法一 + +先打包安装好应用,然后在设备`设置 -> 开机自启` 设置中选择需要自动启动的应用即可,取消开机自启也是在这里设置。 + + +## 设置应用开机自启方法二 + +你也可以通过修改设备中的 `/maixapp/auto_start.txt` 文件来设置,和传输文件的方法请看前面的文档。 +* 首先知道你需要设置的应用的 `id` 是什么。在你打包应用的时候设置的;如果不是你自己打包的应用,可以先安装到设备,查看设备`/maixapp/apps/` 目录下的文件夹名就是应用名,(也可以下载查看设备的`/maixapp/apps/app.info` 文件,`[]`中括号部分就是应用`id`)。 +* 然后写入 `id` 到 `/maixapp/auto_start.txt` 文件即可。(可以在电脑本地创建文件,然后 `MaixVision` 传输到设备。) +* 如果要取消,删除设备上的 `/maixapp/auto_start.txt` 文件即可。 + + +## 其它方法 + +对于 MaixCAM, 因为底层是 Linux, 如果你熟悉 Linux, 编辑`/etc/rc.local` 或者 `/etc/init.d` 下的启动脚本也可以。 + +但是需要注意的是,这种方式会让 MaixVision 在连接的时候无法停止这个应用,从而造成资源占用(比如屏幕和摄像头) MaixVision 可能无法正常跑程序,而前两种方法 MaixVision 连接设备时是可以正常让程序退出以供 MaixVsion 跑程序的。 + +所以这种方法比较适合开机跑一些不会占用屏幕和摄像头等资源的后台进程,一般情况下如果你不熟悉 Linux 不建议这样操作。 + + + + + diff --git a/docs/doc/zh/sidebar.yaml b/docs/doc/zh/sidebar.yaml index ab945d47..1a032f65 100644 --- a/docs/doc/zh/sidebar.yaml +++ b/docs/doc/zh/sidebar.yaml @@ -23,6 +23,8 @@ items: label: 添加额外的 Python 包 - file: basic/app.md label: 应用开发和商店 + - file: basic/auto_start.md + label: 开机自启 - label: 基础图像和算法 items: @@ -32,6 +34,8 @@ items: label: 摄像头使用 - file: vision/image_ops.md label: 基本图像操作 + - file: vision/touchsreen.md + label: 触摸屏使用 - file: vision/find_blobs.md label: 寻找色块 - file: vision/line_tracking.md diff --git a/docs/doc/zh/source_code/build.md b/docs/doc/zh/source_code/build.md index b58c62ad..b1cf6465 100644 --- a/docs/doc/zh/source_code/build.md +++ b/docs/doc/zh/source_code/build.md @@ -19,10 +19,10 @@ cd ~/maix git clone https://github.com/sipeed/MaixCDK ``` -然后需要设置环境变量 `MAIXCAK_PATH` 指定 MaixCDK 的路径,可以在 `~/.bashrc` 或者`~/.zshrc`(根据你使用的shell决定)添加: +然后需要设置环境变量 `MAIXCDK_PATH` 指定 MaixCDK 的路径,可以在 `~/.bashrc` 或者`~/.zshrc`(根据你使用的shell决定)添加: ```shell -export MAIXCAK_PATH=~/maix/MaixCDK +export MAIXCDK_PATH=~/maix/MaixCDK ``` 只有在成功设置环境变量后, MaixPy 才能找到 MaixCDK 源码。 diff --git a/docs/doc/zh/vision/touchscreen.md b/docs/doc/zh/vision/touchscreen.md new file mode 100644 index 00000000..0bb610b2 --- /dev/null +++ b/docs/doc/zh/vision/touchscreen.md @@ -0,0 +1,108 @@ +--- +title: MaixPy / MaixCAM 触摸屏使用方法 +--- + +## 简介 + +对于 MaixCAM 自带了一个触摸屏,写应用时配合触摸屏可以实现很多有趣应用,我们可以通过 API 读取到触摸屏的点按操作。 + +## MaixPy 读取触摸 + +MaixPy 提供了一个简单的`maix.touchscreen.TouchScreen` 类来读取,举例: + +```python +from maix import touchscreen, app, time + +ts = touchscreen.TouchScreen() + +pressed_already = False +last_x = 0 +last_y = 0 +last_pressed = False +while not app.need_exit(): + x, y, pressed = ts.read() + if x != last_x or y != last_y or pressed != last_pressed: + print(x, y, pressed) + last_x = x + last_y = y + last_pressed = pressed + if pressed: + pressed_already = True + else: + if pressed_already: + print(f"clicked, x: {x}, y: {y}") + pressed_already = False + time.sleep_ms(1) # sleep some time to free some CPU usage +``` + +## 配合屏幕实现交互 + +配合屏幕可以做出一些用户交互的内容,更多可以看[MaixPy/examples/vision/touchscreen](https://github.com/sipeed/MaixPy) 目录下例程。 + +如前面的文章介绍的,我们要往屏幕显示内容,一般是得到一个`maix.image.Image`对象,然后调用`disp.show(img)`来显示这张图像。 +实现一个按钮的最原始和简单的方法就是在这个图像上画一个按钮,然后判断用户触摸到这个区域就算是触发了按下事件,注意图像的大小要和屏幕的大小保持一致: +```python +from maix import touchscreen, app, time, display, image + +ts = touchscreen.TouchScreen() +disp = display.Display() + +img = image.Image(disp.width(), disp.height()) + +# draw exit button +exit_label = "< Exit" +size = image.string_size(exit_label) +exit_btn_pos = [0, 0, 8*2 + size.width(), 12 * 2 + size.height()] +img.draw_string(8, 12, exit_label, image.COLOR_WHITE) +img.draw_rect(exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3], image.COLOR_WHITE, 2) + +def is_in_button(x, y, btn_pos): + return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] + +while not app.need_exit(): + x, y, pressed = ts.read() + if is_in_button(x, y, exit_btn_pos): + app.set_exit_flag(True) + img.draw_circle(x, y, 1, image.Color.from_rgb(255, 255, 255), 2) + disp.show(img) +``` + + +## 屏幕和图像大小不一样时如何处理 + +上面的例子可以看到 `img` 大小和屏幕大小一样,如果你的`img`和屏幕大小不一样怎么办(比如上面使用`img = image.Image(240, 240)`,比如屏幕是`640x480`, 图像是`240x240`,`disp.show(img)`的默认行为是`image.Fit.FIT_CONTAIN`, 即把图片放大到`480x480`然后边上填充黑色,如果你在`240x240`的图上画了按钮,比如坐标`(0, 0, 60, 40)`,那么按钮也会自动被放大,所以触摸判断的坐标就不能用`(0, 0, 60, 40)`,需要用`((640 - 480) / 2, 0, 480/240*60, 480/240*40)`, 即`(80, 0, 120, 80)`。 + +这里为了方便缩放图像时,快速计算源图像的点或者矩形框 在 缩放后的目标图像的位置和大小,提供了`image.resize_map_pos`函数来进行此计算过程。 + +```python +from maix import touchscreen, app, time, display, image + +ts = touchscreen.TouchScreen() +disp = display.Display() + +img = image.Image(240, 240) +img.draw_rect(0, 0, img.width(), img.height(), image.COLOR_WHITE) + +# draw exit button +exit_label = "< Exit" +size = image.string_size(exit_label) +exit_btn_pos = [0, 0, 8*2 + size.width(), 12 * 2 + size.height()] +img.draw_string(8, 12, exit_label, image.COLOR_WHITE) +img.draw_rect(exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3], image.COLOR_WHITE, 2) +# 图像按键坐标映射到屏幕上的坐标 +exit_btn_disp_pos = image.resize_map_pos(img.width(), img.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3]) + +def is_in_button(x, y, btn_pos): + return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] + +while not app.need_exit(): + x, y, pressed = ts.read() + if is_in_button(x, y, exit_btn_disp_pos): + app.set_exit_flag(True) + # 屏幕的坐标映射回图像上对应的坐标,然后在图像上画点 + x, y = image.resize_map_pos_reverse(img.width(), img.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, x, y) + img.draw_circle(x, y, 1, image.Color.from_rgb(255, 255, 255), 2) + disp.show(img, fit=image.Fit.FIT_CONTAIN) +``` + + diff --git a/examples/vision/ai_vision/nn_face_recognize.py b/examples/vision/ai_vision/nn_face_recognize.py index 9d733aeb..8773549b 100644 --- a/examples/vision/ai_vision/nn_face_recognize.py +++ b/examples/vision/ai_vision/nn_face_recognize.py @@ -1,33 +1,78 @@ -from maix import nn, camera, display, image, key, time +from maix import nn, camera, display, image, time, touchscreen, app import os import math + recognizer = nn.FaceRecognizer(detect_model="/root/models/retinaface.mud", feature_model = "/root/models/face_feature.mud") # if os.path.exists("/root/faces.bin"): # recognizer.load_faces("/root/faces.bin") cam = camera.Camera(recognizer.input_width(), recognizer.input_height(), recognizer.input_format()) -dis = display.Display() +disp = display.Display() +ts = touchscreen.TouchScreen() +back_btn_pos = (0, 0, 70, 30) # x, y, w, h +learn_btn_pos = (0, recognizer.input_height() - 30, 60, 30) +clear_btn_pos = (recognizer.input_width() - 60, recognizer.input_height() - 30, 60, 30) +back_btn_disp_pos = image.resize_map_pos(cam.width(), cam.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, back_btn_pos[0], back_btn_pos[1], back_btn_pos[2], back_btn_pos[3]) +learn_btn_disp_pos = image.resize_map_pos(cam.width(), cam.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, learn_btn_pos[0], learn_btn_pos[1], learn_btn_pos[2], learn_btn_pos[3]) +clear_btn_disp_pos = image.resize_map_pos(cam.width(), cam.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, clear_btn_pos[0], clear_btn_pos[1], clear_btn_pos[2], clear_btn_pos[3]) +pressed_flag = [False, False, False] + +def draw_btns(img : image.Image): + img.draw_rect(back_btn_pos[0], back_btn_pos[1], back_btn_pos[2], back_btn_pos[3], image.Color.from_rgb(255, 255, 255), 2) + img.draw_string(back_btn_pos[0] + 4, back_btn_pos[1] + 8, "< back", image.COLOR_WHITE) + img.draw_rect(learn_btn_pos[0], learn_btn_pos[1], learn_btn_pos[2], learn_btn_pos[3], image.Color.from_rgb(255, 255, 255), 2) + img.draw_string(learn_btn_pos[0] + 4, learn_btn_pos[1] + 8, "learn", image.COLOR_WHITE) + img.draw_rect(clear_btn_pos[0], clear_btn_pos[1], clear_btn_pos[2], clear_btn_pos[3], image.Color.from_rgb(255, 255, 255), 2) + img.draw_string(clear_btn_pos[0] + 4, clear_btn_pos[1] + 8, "clear", image.COLOR_WHITE) -g_pressed = False +def is_in_button(x, y, btn_pos): + return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] -def on_key(key_id, state): - global g_pressed - print(f"key: {key_id}, state: {state}") - if state == key.State.KEY_RELEASED: - g_pressed = True +def on_touch(x, y, pressed): + ''' + Return learn, clear, ret + ''' + global pressed_flag + if pressed: + if is_in_button(x, y, back_btn_disp_pos): + pressed_flag[2] = True + elif is_in_button(x, y, learn_btn_disp_pos): + pressed_flag[0] = True + elif is_in_button(x, y, clear_btn_disp_pos): + pressed_flag[1] = True + else: # cancel + pressed_flag = [False, False, False] + else: + if pressed_flag[0]: + print("learn btn click") + pressed_flag[0] = False + return True, False, False + if pressed_flag[1]: + print("clear btn click") + pressed_flag[1] = False + return False, True, False + if pressed_flag[2]: + print("back btn click") + pressed_flag[2] = False + return False, False, True + return False, False, False # Init key will cancel the default ok button function(exit app) -btn = key.Key(on_key) learn_id = 0 last_learn_img = None last_learn_t = 0 -while 1: +while not app.need_exit(): + x, y, pressed = ts.read() + learn, clear, back = on_touch(x, y, pressed) + if back: + break + elif clear: + for i in range(len(recognizer.labels) - 1): + recognizer.remove_face(0) img = cam.read() - learn = g_pressed - g_pressed = False faces = recognizer.recognize(img, 0.5, 0.45, 0.8, learn, learn) for obj in faces: color = image.COLOR_RED if obj.class_id == 0 else image.COLOR_GREEN @@ -49,6 +94,7 @@ def on_key(key_id, state): img.draw_image(0, 0, last_learn_img) if learn: recognizer.save_faces("/root/faces.bin") - dis.show(img) + draw_btns(img) + disp.show(img) diff --git a/examples/vision/streaming/send_image_simple.py b/examples/vision/streaming/send_image_simple.py index 2aea2759..ee64c1f2 100644 --- a/examples/vision/streaming/send_image_simple.py +++ b/examples/vision/streaming/send_image_simple.py @@ -7,7 +7,8 @@ img.draw_rect(60, 60, 80, 80, image.Color.from_rgb(255, 0, 0)) # convert to jpeg -jpeg = img.to_format(image.Format.FMT_JPEG) # image.Format.FMT_PNG +jpeg = img.to_jpeg(95) +# jpeg = img.to_format(image.Format.FMT_JPEG) # image.Format.FMT_PNG # get jpeg bytes jpeg_bytes = jpeg.to_bytes() diff --git a/examples/vision/touchscreen/touchscreen_draw.py b/examples/vision/touchscreen/touchscreen_draw.py new file mode 100644 index 00000000..88613b56 --- /dev/null +++ b/examples/vision/touchscreen/touchscreen_draw.py @@ -0,0 +1,57 @@ +from maix import touchscreen, app, time, display, image + +ts = touchscreen.TouchScreen() +disp = display.Display() + +pressed_already = False +last_x = 0 +last_y = 0 +last_pressed = False +img = image.Image(disp.width(), disp.height()) + +# draw exit button +exit_label = "< Exit" +size = image.string_size(exit_label) +exit_btn_pos = [0, 0, 8*2 + size.width(), 12 * 2 + size.height()] + +# draw clear button +clear_label = "Clear" +size = image.string_size(clear_label) +clear_btn_pos = [0, 0, 8*2 + size[0], 12 * 2 + size[1]] +clear_btn_pos[0] = disp.width() - clear_btn_pos[2] + +def draw_btns(img): + img.draw_string(8, 12, exit_label, image.COLOR_WHITE) + img.draw_rect(exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3], image.COLOR_WHITE, 2) + + img.draw_string(clear_btn_pos[0] + 8, 12, clear_label, image.COLOR_WHITE) + img.draw_rect(clear_btn_pos[0], clear_btn_pos[1], clear_btn_pos[2], clear_btn_pos[3], image.COLOR_WHITE, 2) + +def is_in_button(x, y, btn_pos): + return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] + +def on_clicked(x, y): + global img + if is_in_button(x, y, exit_btn_pos): + app.set_exit_flag(True) + elif is_in_button(x, y, clear_btn_pos): + img = image.Image(disp.width(), disp.height()) + draw_btns(img) + +draw_btns(img) +while not app.need_exit(): + x, y, pressed = ts.read() + if x != last_x or y != last_y or pressed != last_pressed: + print(x, y, pressed) + last_x = x + last_y = y + last_pressed = pressed + if pressed: + pressed_already = True + img.draw_circle(x, y, 1, image.Color.from_rgb(255, 255, 255), 2) + else: + if pressed_already: + print(f"clicked, x: {x}, y: {y}") + pressed_already = False + on_clicked(x, y) + disp.show(img) diff --git a/examples/vision/touchscreen/touchscreen_draw_simple.py b/examples/vision/touchscreen/touchscreen_draw_simple.py new file mode 100644 index 00000000..22ca7d95 --- /dev/null +++ b/examples/vision/touchscreen/touchscreen_draw_simple.py @@ -0,0 +1,23 @@ +from maix import touchscreen, app, time, display, image + +ts = touchscreen.TouchScreen() +disp = display.Display() + +img = image.Image(disp.width(), disp.height()) + +# draw exit button +exit_label = "< Exit" +size = image.string_size(exit_label) +exit_btn_pos = [0, 0, 8*2 + size.width(), 12 * 2 + size.height()] +img.draw_string(8, 12, exit_label, image.COLOR_WHITE) +img.draw_rect(exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3], image.COLOR_WHITE, 2) + +def is_in_button(x, y, btn_pos): + return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] + +while not app.need_exit(): + x, y, pressed = ts.read() + if is_in_button(x, y, exit_btn_pos): + app.set_exit_flag(True) + img.draw_circle(x, y, 1, image.Color.from_rgb(255, 255, 255), 2) + disp.show(img) diff --git a/examples/vision/touchscreen/touchscreen_draw_small_img.py b/examples/vision/touchscreen/touchscreen_draw_small_img.py new file mode 100644 index 00000000..92b73265 --- /dev/null +++ b/examples/vision/touchscreen/touchscreen_draw_small_img.py @@ -0,0 +1,26 @@ +from maix import touchscreen, app, time, display, image + +ts = touchscreen.TouchScreen() +disp = display.Display() + +img = image.Image(240, 240) +img.draw_rect(0, 0, img.width(), img.height(), image.COLOR_WHITE) + +# draw exit button +exit_label = "< Exit" +size = image.string_size(exit_label) +exit_btn_pos = [0, 0, 8*2 + size.width(), 12 * 2 + size.height()] +img.draw_string(8, 12, exit_label, image.COLOR_WHITE) +img.draw_rect(exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3], image.COLOR_WHITE, 2) +exit_btn_disp_pos = image.resize_map_pos(img.width(), img.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, exit_btn_pos[0], exit_btn_pos[1], exit_btn_pos[2], exit_btn_pos[3]) + +def is_in_button(x, y, btn_pos): + return x > btn_pos[0] and x < btn_pos[0] + btn_pos[2] and y > btn_pos[1] and y < btn_pos[1] + btn_pos[3] + +while not app.need_exit(): + x, y, pressed = ts.read() + if is_in_button(x, y, exit_btn_disp_pos): + app.set_exit_flag(True) + x, y = image.resize_map_pos_reverse(img.width(), img.height(), disp.width(), disp.height(), image.Fit.FIT_CONTAIN, x, y) + img.draw_circle(x, y, 1, image.Color.from_rgb(255, 255, 255), 2) + disp.show(img, fit=image.Fit.FIT_CONTAIN) diff --git a/examples/vision/touchscreen/touchscreen_read.py b/examples/vision/touchscreen/touchscreen_read.py new file mode 100644 index 00000000..943399a0 --- /dev/null +++ b/examples/vision/touchscreen/touchscreen_read.py @@ -0,0 +1,22 @@ +from maix import touchscreen, app, time + +ts = touchscreen.TouchScreen() + +pressed_already = False +last_x = 0 +last_y = 0 +last_pressed = False +while not app.need_exit(): + x, y, pressed = ts.read() + if x != last_x or y != last_y or pressed != last_pressed: + print(x, y, pressed) + last_x = x + last_y = y + last_pressed = pressed + if pressed: + pressed_already = True + else: + if pressed_already: + print(f"clicked, x: {x}, y: {y}") + pressed_already = False + time.sleep_ms(1) # sleep some time to free some CPU usage diff --git a/maix/version.py b/maix/version.py index 12b9fb75..37dcef09 100644 --- a/maix/version.py +++ b/maix/version.py @@ -2,7 +2,7 @@ # Versions should comply with PEP440: https://peps.python.org/pep-0440/ version_major = 4 -version_minor = 1 -version_patch = 4 +version_minor = 2 +version_patch = 0 __version__ = "{}.{}.{}".format(version_major, version_minor, version_patch)