├── envs ├── __init__.py ├── windows.py └── utils.py ├── maix ├── _maix_vision_ │ ├── __init__.py │ └── histogram.py ├── nn │ ├── app │ │ ├── face │ │ │ └── __init__.py │ │ ├── classifier │ │ │ └── __init__.py │ │ └── __init__.py │ ├── __init__.py │ └── decoder │ │ └── __init__.py ├── serial.py ├── spi.py ├── utils.py ├── image.py ├── __init__.py ├── gpio.py ├── event.py ├── display.py ├── i2c.py ├── zbar.py └── pwm.py ├── ext_modules ├── _maix_image │ ├── example │ │ ├── maix_version_find_ball_color.py │ │ ├── test_image.jpg │ │ ├── test_crop_affine.jpg │ │ ├── maix_image_histeq.py │ │ ├── maix_image_mean.py │ │ ├── maix_image_lens_corr.py │ │ ├── test_crop_affine.py │ │ ├── maix_versionget_blob_color.py │ │ ├── maix_opencv_image_test.py │ │ ├── test_maix_image.py │ │ ├── maix_image_draw_base.py │ │ ├── maix_version_find_line.py │ │ ├── maix_image_get_histogram.py │ │ ├── maix_version_find_blobs.py │ │ └── maix_image_base_test.py │ ├── doc │ │ └── Module_Development_Guide.md │ └── include │ │ └── costom_imlib_config.h ├── libi2c │ ├── help.py │ ├── setup.py │ ├── example │ │ ├── Makefile │ │ ├── i2c_without_internal_address.c │ │ ├── pylibi2c_tools.py │ │ └── i2c_tools.c │ ├── Makefile │ ├── src │ │ └── i2c.h │ └── README.md ├── _maix │ ├── include │ │ └── _maix.h │ ├── example │ │ └── test__maix.py │ └── _maix.c ├── _maix_nn │ ├── example │ │ ├── test__maix_nn.py │ │ ├── test_maix_nn.py │ │ ├── load_forward.py │ │ ├── test_load_forward_sobel_edge.py │ │ ├── load_forward_sobel_edge.py │ │ ├── load_forward_camera.py │ │ ├── load_forward_sobel_edge_camera.py │ │ ├── r329_sobel.py │ │ ├── r329_mobilenet2.py │ │ ├── r329_resnet50.py │ │ ├── r329_shufflenet.py │ │ ├── person.py │ │ ├── yolo2_image.py │ │ ├── r329_yolo2_person.py │ │ ├── r329_yolo2_camera.py │ │ ├── r329_yolo2_cards.py │ │ ├── Retinaface.py │ │ └── self_learn_classifier.py │ ├── src │ │ ├── py_maix_nn_decoder.c │ │ ├── py_maix_nn_app.c │ │ ├── py_maix_nn.c │ │ └── py_maix_nn_funtional.c │ └── include │ │ ├── py_maix_nn_classifier.h │ │ ├── py_maix_nn_FaceRecognize.h │ │ └── py_maix_nn.h ├── _maix_camera │ ├── example │ │ └── test__maix_camera.py │ ├── include │ │ └── _maix_camera.h │ └── _camera_pybind.cpp ├── _maix_display │ ├── example │ │ ├── test__maix_display.py │ │ ├── test_maix_r329display.py │ │ └── pyav2pyaudio&display.py │ ├── include │ │ └── _maix_display.h │ └── _dispay_pybind11.cpp ├── _maix_nn_mud │ ├── src │ │ ├── py_maix_nn_decoder.c │ │ ├── py_maix_nn_app.c │ │ └── py_maix_nn.c │ ├── include │ │ ├── py_maix_nn_classifier.h │ │ ├── py_maix_nn_FaceRecognize.h │ │ └── py_maix_nn.h │ └── example │ │ ├── hand.py │ │ ├── v831_yolo2_person_class_mdsc.py │ │ ├── mask.py │ │ ├── person.py │ │ ├── retinaface.py │ │ └── LPR.py ├── _maix_vivo │ └── example │ │ └── _maix_vivo.py ├── _maix_nn_functional │ ├── src │ │ └── py_maix_nn_function.cpp │ └── include │ │ └── py_maix_nn_function.h ├── _maix_speech │ └── example │ │ ├── test_mic_input.py │ │ └── test_maix_speech.py └── _maix_nn_decoder │ └── py_maix_nn_decoder_ctc.cpp ├── docs ├── uasge.png ├── clear.py ├── pwm.md └── develop.md ├── .gitmodules ├── tests ├── maix_v831 │ ├── labels.txt │ ├── usage_v831_spidev1.0.py │ ├── usage_v831_ttyS1.py │ ├── usage_v831_gdadc_keys.py │ ├── usage_v831_gpio.py │ ├── usage_v831_adc.py │ ├── usage_v831_pwm6-9.py │ ├── yolo2.py │ ├── play_camera_mp4.py │ ├── self_classifier.py │ └── usage_v831_watchdog.py ├── general │ ├── usage_maix.py │ ├── uasge_evdev.py │ └── usage_desktop.py └── test_rpyc.py ├── tox.ini ├── MANIFEST.in ├── LICENSE ├── .github └── workflows │ ├── maixpy3_build.yml │ └── maixpy3_pypi.yml ├── setup.py ├── .gitignore └── README.md /envs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /maix/_maix_vision_/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_version_find_ball_color.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/uasge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipeed/MaixPy3/HEAD/docs/uasge.png -------------------------------------------------------------------------------- /ext_modules/libi2c/help.py: -------------------------------------------------------------------------------- 1 | import pylibi2c 2 | help(pylibi2c) 3 | help(pylibi2c.I2CDevice) 4 | -------------------------------------------------------------------------------- /maix/nn/app/face/__init__.py: -------------------------------------------------------------------------------- 1 | from _maix_nn import _app 2 | FaceRecognize = _app.FaceRecognize 3 | -------------------------------------------------------------------------------- /maix/serial.py: -------------------------------------------------------------------------------- 1 | 2 | try: 3 | from serial import * 4 | except ModuleNotFoundError as e: 5 | pass 6 | -------------------------------------------------------------------------------- /maix/spi.py: -------------------------------------------------------------------------------- 1 | 2 | try: 3 | from spidev import * 4 | except ModuleNotFoundError as e: 5 | pass 6 | -------------------------------------------------------------------------------- /maix/utils.py: -------------------------------------------------------------------------------- 1 | 2 | try: 3 | from _maix import * 4 | except ModuleNotFoundError as e: 5 | pass 6 | -------------------------------------------------------------------------------- /maix/image.py: -------------------------------------------------------------------------------- 1 | 2 | try: 3 | from _maix_image import * 4 | except ModuleNotFoundError as e: 5 | pass 6 | -------------------------------------------------------------------------------- /maix/nn/app/classifier/__init__.py: -------------------------------------------------------------------------------- 1 | from _maix_nn import _app 2 | load = _app.classifier_load 3 | Classifier = _app.Classifier 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext_modules/libmaix"] 2 | path = ext_modules/libmaix 3 | url = https://github.com/sipeed/libmaix 4 | branch = release -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/test_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipeed/MaixPy3/HEAD/ext_modules/_maix_image/example/test_image.jpg -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/test_crop_affine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sipeed/MaixPy3/HEAD/ext_modules/_maix_image/example/test_crop_affine.jpg -------------------------------------------------------------------------------- /maix/nn/app/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # try: 3 | # from . import classifier 4 | # from . import face 5 | # except ModuleNotFoundError as e: 6 | # pass 7 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_image_histeq.py: -------------------------------------------------------------------------------- 1 | from maix import display, image 2 | import time 3 | tmp = image.Image() 4 | tmp.open("/home/lyx/Desktop/src2.png") 5 | tmp = tmp.histeq() 6 | display.show(tmp) 7 | time.sleep(10) -------------------------------------------------------------------------------- /tests/maix_v831/labels.txt: -------------------------------------------------------------------------------- 1 | char* labels[] = {"aeroplane","bicycle","bird","boat","bottle","bus","car","cat","chair","cow","diningtable","dog","horse","motorbike","person","pottedplant","sheep","sofa","train","tvmonitor"}; 2 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_image_mean.py: -------------------------------------------------------------------------------- 1 | from maix import display, image 2 | import time 3 | tmp = image.Image() 4 | tmp.open("/home/lyx/images/test_filter.jpg") 5 | tmp = tmp.mean(2) 6 | display.show(tmp) 7 | time.sleep(10) -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_image_lens_corr.py: -------------------------------------------------------------------------------- 1 | from maix import display, image 2 | import time 3 | tmp = image.Image() 4 | tmp.open("/home/lyx/images/test_filter.jpg") 5 | tmp = tmp.lens_corr() 6 | display.show(tmp) 7 | time.sleep(10) -------------------------------------------------------------------------------- /ext_modules/_maix/include/_maix.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPY_MAIX_H_ 2 | #define _CPY_MAIX_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /maix/nn/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | try: 3 | from _maix_nn import * 4 | from . import decoder 5 | from . import app 6 | 7 | from _maix_nn import F, load 8 | 9 | # from .import nn_new 10 | except ModuleNotFoundError as e: 11 | pass 12 | -------------------------------------------------------------------------------- /ext_modules/_maix/example/test__maix.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import py 3 | import pytest 4 | 5 | def test_import(): 6 | import _maix 7 | print(_maix.help()) 8 | tmp = _maix.rgb2jpg(b"\xff"*4*6*3, 4, 6) 9 | print(len(tmp)) 10 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/test_crop_affine.py: -------------------------------------------------------------------------------- 1 | from maix import image 2 | 3 | img = image.open("test_crop_affine.jpg") 4 | 5 | print(img.size) 6 | 7 | tmp = img.crop_affine([204, 205, 64, 202, 68, 154], 94, 24) 8 | 9 | tmp.save('test_crop_affine.png') 10 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/test__maix_nn.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import py 3 | import pytest 4 | 5 | def test_import(): 6 | try: 7 | import _maix_nn 8 | print(_maix_nn.__version__) 9 | _maix_nn.help() 10 | except ModuleNotFoundError as e: 11 | pass 12 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_versionget_blob_color.py: -------------------------------------------------------------------------------- 1 | from maix import image, display, camera 2 | import time 3 | 4 | 5 | def test_get_blob_color(): 6 | img = image.new(color=(100, 100, 200)) 7 | colors = img.get_blob_color((100, 100, 10, 10), 0, 0) 8 | print(colors) 9 | 10 | 11 | test_get_blob_color() 12 | -------------------------------------------------------------------------------- /tests/maix_v831/usage_v831_spidev1.0.py: -------------------------------------------------------------------------------- 1 | import spidev 2 | spi = spidev.SpiDev() 3 | spi.open(1, 0) 4 | 5 | spi.bits_per_word = 8 6 | spi.max_speed_hz = 1 7 | spi.mode = 0b11 8 | 9 | import time 10 | 11 | while True: 12 | time.sleep(0.1) 13 | to_send = [0x01, 0x02, 0x01] 14 | print(spi.xfer2(to_send, 800000)) # 800Khz 15 | 16 | -------------------------------------------------------------------------------- /maix/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | version='0.5.4' 3 | 4 | __all__ = ['display', 'camera', 'image'] 5 | 6 | try: 7 | from . import nn 8 | __all__.extend(['nn']) 9 | except ModuleNotFoundError as e: 10 | pass 11 | 12 | import signal # v831 need release mpp, maybe have bug so remove. 13 | signal.signal(signal.SIGINT,lambda signum,frame:exit(0)) 14 | -------------------------------------------------------------------------------- /ext_modules/_maix_camera/example/test__maix_camera.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import py 3 | import pytest 4 | 5 | def test_import(): 6 | import _maix_camera 7 | print(_maix_camera.VirtualCamera()) 8 | 9 | ''' 10 | 11 | import _maix_camera 12 | cam = _maix_camera.Camera(240,240,0) 13 | img_bytes = cam.read() 14 | img_bytes =img_bytes[1] 15 | 16 | ''' 17 | -------------------------------------------------------------------------------- /envs/windows.py: -------------------------------------------------------------------------------- 1 | 2 | from setuptools import Extension 3 | from .utils import get_srcs 4 | 5 | _maix_modules = [ 6 | 7 | ] 8 | 9 | _maix_data_files = [ 10 | 11 | ] 12 | 13 | _maix_py_modules = [ 14 | "Pillow", 15 | "numpy", 16 | "opencv-python==4.1.2.30", 17 | "opencv-contrib-python==4.1.2.30", 18 | "Pillow", 19 | "rpyc", 20 | "pyserial" 21 | ] 22 | -------------------------------------------------------------------------------- /tests/general/usage_maix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from maix import display, camera 4 | while True: 5 | display.show( 6 | display.as_image() 7 | .draw_rectangle(0, 0, display.width(), display.height(), color=(0, 0, 0), thickness=-1) 8 | .draw_image( 9 | camera.capture() 10 | .resize(size=(224, 224)), alpha=0.9 11 | ) 12 | ) 13 | 14 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # Tox (http://tox.testrun.org/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py38 8 | 9 | [testenv] 10 | passenv = LC_ALL, LANG 11 | commands = py.test 12 | deps = 13 | pytest 14 | scripttest 15 | Pillow 16 | pexpect 17 | rpyc -------------------------------------------------------------------------------- /tests/maix_v831/usage_v831_ttyS1.py: -------------------------------------------------------------------------------- 1 | import serial 2 | 3 | ser = serial.Serial("/dev/ttyS1",115200) 4 | 5 | print('serial test start ...') 6 | ser.write(b"Hello Wrold !!!\n") 7 | try: 8 | while True: 9 | ser.setDTR(True) 10 | ser.setRTS(True) 11 | tmp = ser.readline() 12 | print(tmp) 13 | ser.write(tmp) 14 | ser.setDTR(False) 15 | ser.setRTS(False) 16 | except KeyboardInterrupt: 17 | if ser != None: 18 | ser.close() -------------------------------------------------------------------------------- /maix/nn/decoder/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | try: 5 | from _maix_nn_decoder_retinaface import * 6 | except ModuleNotFoundError as e: 7 | pass 8 | try: 9 | from _maix_nn_decoder_license_plate_location import * 10 | except ModuleNotFoundError as e: 11 | pass 12 | try: 13 | from _maix_nn_decoder_CTC import * 14 | except ModuleNotFoundError as e: 15 | pass 16 | 17 | try: 18 | from _maix_nn import _decoder 19 | Yolo2 = _decoder.Yolo2 20 | except ModuleNotFoundError as e: 21 | pass 22 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/test_maix_nn.py: -------------------------------------------------------------------------------- 1 | import _maix_nn 2 | 3 | model = { 4 | "bin": "/root/video/resnet.bin" 5 | } 6 | 7 | options = { 8 | "model_type": "aipu", 9 | "inputs": { 10 | "input0": (224, 224, 3) 11 | }, 12 | "outputs": { 13 | "output0": (1, 1, 1000) 14 | }, 15 | "first_layer_conv_no_pad": False, 16 | "mean": [127.5, 127.5, 127.5], 17 | "norm": [0.0176, 0.0176, 0.0176], 18 | } 19 | print("-- load model:", model) 20 | m = _maix_nn.load(model, opt=options) 21 | print("-- load ok") 22 | -------------------------------------------------------------------------------- /ext_modules/_maix_display/example/test__maix_display.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from PIL import Image 4 | 5 | from maix import display 6 | 7 | display.show(Image.new("RGB", (320, 240), (0, 0xFF, 0))) 8 | 9 | from maix import camera 10 | 11 | for i in range(30): 12 | display.show(camera.read()) 13 | 14 | print(display.__draw__) 15 | 16 | display.show(Image.new("RGB", (22, 22), (0xFF, 0, 0))) 17 | 18 | import time 19 | 20 | time.sleep(2) 21 | 22 | display.clear() 23 | 24 | display.show(Image.new("RGB", (22, 22), (0, 0, 0xFF))) 25 | 26 | time.sleep(2) 27 | 28 | # bytes 29 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/src/py_maix_nn_decoder.c: -------------------------------------------------------------------------------- 1 | 2 | #include "Python.h" 3 | #include "py_maix_nn.h" 4 | 5 | #include 6 | #include 7 | 8 | 9 | static PyMethodDef _maix_nn_decoder_methods[] = { 10 | 11 | {NULL, NULL, 0, NULL} 12 | }; 13 | 14 | 15 | struct PyModuleDef maix_nn_decoder_module = { 16 | PyModuleDef_HEAD_INIT, 17 | "decoder", /* Module name */ 18 | _maix_nn_decoder_doc, /* Module _maixMethods */ 19 | -1, /* size of per-interpreter state of the module, size of per-interpreter state of the module,*/ 20 | _maix_nn_decoder_methods, 21 | }; 22 | 23 | 24 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/src/py_maix_nn_decoder.c: -------------------------------------------------------------------------------- 1 | 2 | #include "Python.h" 3 | #include "py_maix_nn.h" 4 | 5 | #include 6 | #include 7 | 8 | 9 | static PyMethodDef _maix_nn_decoder_methods[] = { 10 | 11 | {NULL, NULL, 0, NULL} 12 | }; 13 | 14 | 15 | struct PyModuleDef maix_nn_decoder_module = { 16 | PyModuleDef_HEAD_INIT, 17 | "decoder", /* Module name */ 18 | _maix_nn_decoder_doc, /* Module _maixMethods */ 19 | -1, /* size of per-interpreter state of the module, size of per-interpreter state of the module,*/ 20 | _maix_nn_decoder_methods, 21 | }; 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/maix_v831/usage_v831_gdadc_keys.py: -------------------------------------------------------------------------------- 1 | 2 | from fcntl import ioctl 3 | import struct 4 | import sys 5 | import os 6 | import time 7 | 8 | from evdev import InputDevice 9 | from select import select 10 | 11 | 12 | def detectInputKey(count): 13 | dev = InputDevice('/dev/input/event0') 14 | while True: 15 | select([dev], [], []) 16 | for event in dev.read(): 17 | # print(event) 18 | if event.code == 0x02: 19 | print('press key S1') 20 | if event.code == 0x03: 21 | print('press key S2') 22 | if event.value == 1 and event.code != 0: 23 | count += 1 24 | print('press sum:', count) 25 | 26 | detectInputKey(0) 27 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/include/py_maix_nn_classifier.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPY_MAIX_NN_CLASSIFIER_H_ 2 | #define _CPY_MAIX_NN_CLASSIFIER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "libmaix_nn.h" 10 | #include "py_maix_nn.h" 11 | 12 | typedef struct 13 | { 14 | PyObject_HEAD; 15 | ModelObject* nn_model; 16 | int class_num; 17 | int sample_num; 18 | int feature_len; 19 | int input_w; 20 | int input_h; 21 | void* classifier_obj; 22 | bool init; 23 | } App_Classifier_Object; 24 | 25 | extern PyTypeObject PyMaix_NN_app_Classifier_Type; 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/include/py_maix_nn_classifier.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPY_MAIX_NN_CLASSIFIER_H_ 2 | #define _CPY_MAIX_NN_CLASSIFIER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "libmaix_nn.h" 10 | #include "py_maix_nn.h" 11 | 12 | typedef struct 13 | { 14 | PyObject_HEAD; 15 | ModelObject* nn_model; 16 | int class_num; 17 | int sample_num; 18 | int feature_len; 19 | int input_w; 20 | int input_h; 21 | void* classifier_obj; 22 | bool init; 23 | } App_Classifier_Object; 24 | 25 | extern PyTypeObject PyMaix_NN_app_Classifier_Type; 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /ext_modules/_maix_display/example/test_maix_r329display.py: -------------------------------------------------------------------------------- 1 | 2 | from PIL import Image 3 | 4 | from _maix_display import Display 5 | 6 | __show__ = Display() 7 | 8 | canvas = Image.new("RGB", (240, 240), "#ff1b50") 9 | __show__ = Display() 10 | mk = canvas.tobytes() 11 | __show__.draw(mk, 240, 240) 12 | 13 | canvas = Image.new("RGB", (240, 240), "#501bff") 14 | mk = canvas.tobytes() 15 | __show__.draw(mk, 240, 240) 16 | 17 | ''' 18 | import _maix_camera 19 | from _maix_display import Display 20 | cam = _maix_camera.Camera(240,240,0) 21 | __show__ = Display(240, 240) 22 | 23 | while True: 24 | img_bytes = cam.read() 25 | if img_bytes[0]: 26 | __show__.draw(img_bytes[1],240,240) 27 | 28 | ''' -------------------------------------------------------------------------------- /ext_modules/_maix_vivo/example/_maix_vivo.py: -------------------------------------------------------------------------------- 1 | 2 | from maix import camera 3 | 4 | print(camera.camera.cam.cfg(240, 240, 0)) 5 | img = camera.camera.cam.get() 6 | print(len(img[0])) 7 | 8 | print(camera.camera.cam.cfg(320, 240, 0)) 9 | img = camera.camera.cam.get() 10 | print(len(img[0])) 11 | 12 | # camera.config(size=(240, 240)) 13 | 14 | # camera.config(size=(320, 240)) 15 | 16 | from _maix_vivo import _v83x_vivo 17 | cam = _v83x_vivo(320, 240) 18 | 19 | print(cam.cfg(240, 240, 0)) 20 | frame = cam.get() 21 | print(len(frame)) 22 | if len(frame) > 0: 23 | print(len(frame[0])) 24 | 25 | print(cam.cfg(320, 240, 0)) 26 | frame = cam.get() 27 | print(len(frame)) 28 | if len(frame) > 0: 29 | print(len(frame[0])) 30 | 31 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | 2 | graft docs 3 | graft envs 4 | graft tests 5 | 6 | graft ext_modules 7 | prune ext_modules/_maix_speech/Maix-Speech/.git 8 | prune ext_modules/_maix_speech/Maix-Speech/assets 9 | prune ext_modules/_maix_speech/Maix-Speech/projects 10 | prune ext_modules/_maix_speech/Maix-Speech/tools 11 | 12 | prune .git 13 | prune tests 14 | 15 | prune ext_modules/libmaix/assets 16 | prune ext_modules/libmaix/examples 17 | prune ext_modules/libmaix/tools 18 | 19 | recursive-include ext_modules/libmaix/components/libmaix/include *.h 20 | recursive-include ext_modules/libmaix/components/maix_cv_image/include *.h 21 | recursive-include ext_modules/libmaix/components/libmaix/lib/arch/desktop/ * 22 | 23 | global-exclude __pycache__ *.log *.pyc 24 | 25 | global-exclude *.py[cod] 26 | -------------------------------------------------------------------------------- /ext_modules/libi2c/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | setup.py file for pylibi2c 5 | """ 6 | 7 | from distutils.core import setup, Extension 8 | 9 | pylibi2c_module = Extension('pylibi2c', sources=['src/i2c.c', 'src/pyi2c.c'],) 10 | 11 | setup( 12 | name='pylibi2c', 13 | version='0.2', 14 | license='MIT', 15 | author='Amaork', 16 | author_email="amaork@gmail.com", 17 | url='https://github.com/amaork/libi2c', 18 | description="Linux userspace i2c operation library", 19 | long_description=open('README.md').read(), 20 | ext_modules=[pylibi2c_module], 21 | py_modules=["pylibi2c"], 22 | classifiers=[ 23 | 'Programming Language :: Python', 24 | 'Programming Language :: Python :: 2', 25 | 'Programming Language :: Python :: 3', 26 | ], 27 | ) 28 | 29 | 30 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/include/py_maix_nn_FaceRecognize.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPY_MAIX_NN_FACERECOGNIZE_H_ 2 | #define _CPY_MAIX_NN_FACERECOGNIZE_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "libmaix_nn.h" 10 | #include "py_maix_nn.h" 11 | 12 | typedef struct 13 | { 14 | PyObject_HEAD; 15 | ModelObject* detect_model; 16 | ModelObject* fea_model; 17 | int fea_len; 18 | void* recognize_obj; 19 | float* fea_temp; 20 | float* fea_temp2; 21 | int input_w; 22 | int input_h; 23 | int input_c; 24 | bool init; 25 | PyObject* pillow_image_module; 26 | } App_FaceRecognize_Object; 27 | 28 | extern PyTypeObject PyMaix_NN_app_FaceRecognize_Type; 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/include/py_maix_nn_FaceRecognize.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPY_MAIX_NN_FACERECOGNIZE_H_ 2 | #define _CPY_MAIX_NN_FACERECOGNIZE_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "libmaix_nn.h" 10 | #include "py_maix_nn.h" 11 | 12 | typedef struct 13 | { 14 | PyObject_HEAD; 15 | ModelObject* detect_model; 16 | ModelObject* fea_model; 17 | int fea_len; 18 | void* recognize_obj; 19 | float* fea_temp; 20 | float* fea_temp2; 21 | int input_w; 22 | int input_h; 23 | int input_c; 24 | bool init; 25 | PyObject* pillow_image_module; 26 | } App_FaceRecognize_Object; 27 | 28 | extern PyTypeObject PyMaix_NN_app_FaceRecognize_Type; 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /ext_modules/libi2c/example/Makefile: -------------------------------------------------------------------------------- 1 | CC = $(CROSS)gcc 2 | AR = $(CROSS)ar 3 | CFLAGS = -Wall -g 4 | LDSHFLAGS = -rdynamic -shared 5 | ARFLAGS = rcv 6 | CFLAGS += -I../src 7 | LDFLAGS = -L.. -li2c -Wl,-R -Wl,.. 8 | 9 | OBJDIR=../objs 10 | SOURCES = $(wildcard *.c) $(wildcard *.cpp) 11 | TARGETS = $(foreach src, $(SOURCES), $(basename $(src))) 12 | 13 | .PHONY:all clean objdir 14 | .SILENT:clean 15 | 16 | all:objdir $(TARGETS) 17 | 18 | objdir: 19 | @mkdir -p $(OBJDIR) 20 | 21 | clean: 22 | $(RM) *.o a.out depend $(TARGETS) $(OBJDIR) -rf 23 | 24 | i2c_tools: i2c_tools.o 25 | $(CC) $(CFLAGS) -o $(OBJDIR)/$@ $^ $(LDFLAGS) 26 | 27 | i2c_without_internal_address: i2c_without_internal_address.o 28 | $(CC) $(CFLAGS) -o $(OBJDIR)/$@ $^ $(LDFLAGS) 29 | 30 | depend:$(wildcard *.h *.c) 31 | $(CC) $(CFLAGS) -MM $^ > $@ 32 | 33 | -include depend 34 | -------------------------------------------------------------------------------- /tests/maix_v831/usage_v831_gpio.py: -------------------------------------------------------------------------------- 1 | 2 | from gpiod import chip, line, line_request 3 | gpiochip1 = chip("gpiochip1") 4 | 5 | def pin(gpio="PD", pos=11): 6 | return 32 * (ord(gpio.lower()[1]) - ord('a')) + pos 7 | 8 | def gpio(line_offset=(224 + 14), line_mode = line_request.DIRECTION_OUTPUT): # "default PH14 OUTPUT" 9 | try: 10 | tmp = None 11 | tmp = gpiochip1.get_line(line_offset) 12 | config = line_request() # led.active_state == line.ACTIVE_LOW 13 | config.request_type = line_mode # line.DIRECTION_INPUT 14 | tmp.request(config) 15 | except Exception as e: 16 | print(e) 17 | finally: 18 | return tmp 19 | 20 | import time 21 | led = gpio(pin("PH", 14)) 22 | while led: 23 | led.set_value(0) 24 | time.sleep(0.5) 25 | print("0", led.get_value()) 26 | led.set_value(1) 27 | time.sleep(0.5) 28 | print("1", led.get_value()) 29 | -------------------------------------------------------------------------------- /maix/_maix_vision_/histogram.py: -------------------------------------------------------------------------------- 1 | # //================================================================== 2 | # //函数名: _maix_visionpy.histogram类说明 3 | # //作者: dianjixz 4 | # //日期: 2021-10-29 5 | # //功能说明: 直方图对象是由 vision.get_histogram 返回。 灰度直方图有一个包 6 | # // 含多个二进制的通道。所有二进制都进行标准化,使其总和为1。RGB888 7 | # // 有三个包含多个二进制的通道。所有二进制都进行标准化,使其总和为1。 8 | # //输入参数: vision.opecv_Canny(img, thr_h, thr_l, size=(0,0),mode=0) 9 | # // py_img 图像对象,PIL图像或bytes图像(如果不是240*240的rgb数据需要提供size和mode参数) 10 | # // thr_h 最大阈值 11 | # // thr_l 最小阈值 12 | # // size 图像的尺寸(非必须,默认240*240) 13 | # // mode 图像的格式(非必须,默认vision.COLOR_RGB) 14 | # //返回值: 15 | # // 返回边缘检测函数后的图像,图像格式和输入保持一致; 16 | # //修改记录: 17 | # //================================================================== 18 | class histogram(list): 19 | pass -------------------------------------------------------------------------------- /ext_modules/_maix_display/include/_maix_display.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIX_DISPLAY_H 2 | #define _MAIX_DISPLAY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | // #include 11 | #include "libmaix_disp.h" 12 | #include "libmaix_cam.h" 13 | #define debug_line // printf("%s:%d %s %s %s \r\n", __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__) 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | 19 | class _Display 20 | { 21 | private: 22 | public: 23 | libmaix_disp_t *disp; 24 | int width ; 25 | int height ; 26 | int bpp; 27 | libmaix_image_t *display_image; 28 | _Display(); 29 | ~_Display(); 30 | pybind11::object draw(pybind11::object py_img,int img_w,int img_h,int mode); 31 | void close(); 32 | void __enter__(); 33 | void __exit__(); 34 | 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ext_modules/libi2c/example/i2c_without_internal_address.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "i2c.h" 5 | 6 | int main(int argc, char **argv) 7 | { 8 | int fd; 9 | I2CDevice device; 10 | const char *data = "9876543"; 11 | 12 | /* First open i2c bus */ 13 | if ((fd = i2c_open("/dev/i2c-0")) == -1) { 14 | 15 | perror("Open i2c bus error"); 16 | return -1; 17 | } 18 | 19 | /* Fill i2c device struct */ 20 | device.bus = fd; 21 | device.addr = 0x12; 22 | device.tenbit = 0; 23 | device.delay = 10; 24 | device.flags = 0; 25 | device.page_bytes = 8; 26 | device.iaddr_bytes = 0; /* Set this to zero, and using i2c_ioctl_xxxx API will ignore chip internal address */ 27 | 28 | /* Write data to i2c */ 29 | if (i2c_ioctl_write(&device, 0x0, data, strlen(data)) != strlen(data)) { 30 | 31 | /* Error process */ 32 | } 33 | 34 | i2c_close(fd); 35 | return 0; 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_opencv_image_test.py: -------------------------------------------------------------------------------- 1 | 2 | import time 3 | from maix import display, camera 4 | from _maix_display import Display 5 | import _maix_image 6 | from PIL import Image 7 | from maix import camera 8 | from maix.image import Image 9 | from maix import display, camera, Image 10 | from maix import display, camera, image 11 | 12 | 13 | def show_run_time(func): 14 | import timeit 15 | 16 | def time_get(): 17 | elapsed_time = timeit.timeit(stmt=func, number=1) 18 | print(func, elapsed_time) 19 | return time_get 20 | 21 | 22 | @show_run_time 23 | def test_quick(): 24 | tmp = camera.read() 25 | display.show(tmp) 26 | 27 | 28 | # 0.011696916999881068 29 | test_quick() 30 | 31 | @show_run_time 32 | def test_pillow(): 33 | tmp = camera.capture() 34 | display.show(tmp.resize((240, 240))) 35 | 36 | 37 | # 0.07056433300022036 38 | test_pillow() 39 | 40 | display.show(camera.capture()) 41 | 42 | -------------------------------------------------------------------------------- /tests/maix_v831/usage_v831_adc.py: -------------------------------------------------------------------------------- 1 | 2 | class v83x_ADC(): 3 | def __init__(self, addr=b"0x05070080") -> None: 4 | self.addr = addr 5 | self.path = "/sys/class/sunxi_dump/dump" 6 | self.file = open(self.path, "wb+") 7 | self.last = self.value() 8 | def __del__(self): 9 | try: 10 | if self.file: 11 | self.file.close() 12 | del self.file 13 | except Exception as e: 14 | pass 15 | def value(self): 16 | self.file.write(b"0x05070080") 17 | self.file.seek(0) 18 | return int(self.file.read()[:-1], 16) 19 | 20 | if __name__ == '__main__': 21 | import time 22 | from maix import camera, display, image 23 | v831_adc0 = v83x_ADC() 24 | while True: 25 | time.sleep(0.1) 26 | tmp = image.new((240, 240), (0x2c, 0x3e, 0x50), "RGB") 27 | val = v831_adc0.value() 28 | print(val) 29 | img = image.Image().open('/home/res/logo.png') 30 | tmp.draw_image(img, 50, 40, alpha=1).draw_string(20, 200, "adc0 : " + str(val), 1, (0xbd, 0xc3, 0xc7)) 31 | display.show(tmp) 32 | 33 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/load_forward.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | from maix import nn 5 | from maix import display,camera 6 | from classes_label import labels 7 | import time 8 | 9 | model = { 10 | "param": "/home/model/resnet18_1000_awnn.param", 11 | "bin": "/home/model/resnet18_1000_awnn.bin" 12 | # "bin": "./resnet.bin" 13 | } 14 | options = { 15 | "model_type": "awnn", 16 | "inputs": { 17 | "input0": (224, 224, 3) 18 | }, 19 | "outputs": { 20 | "output0": (1, 1, 1000) 21 | }, 22 | "first_layer_conv_no_pad": False, 23 | "mean": [127.5, 127.5, 127.5], 24 | "norm": [0.0176, 0.0176, 0.0176], 25 | } 26 | print("-- load model:", model) 27 | m = nn.load(model, opt=options) 28 | print("-- load ok") 29 | 30 | while True: 31 | img = camera.capture().resize(size=(224, 224)) 32 | out = m.forward(img.tobytes(), quantize=True) 33 | out2 = nn.F.softmax(out) 34 | msg = "{:.2f}: {}".format(out2.max(), labels[out.argmax()]) 35 | img.draw_string(0,0,msg,scale = 0.5 , color = (183,127,221)) 36 | display.show(img) -------------------------------------------------------------------------------- /tests/maix_v831/usage_v831_pwm6-9.py: -------------------------------------------------------------------------------- 1 | from maix import pwm 2 | 3 | import time 4 | 5 | # period = 1000000 # 表示 pwm 的周期,单位 ns 6 | # duty_cycle = 500000 # 表示占空比,单位 ns 7 | # polarity = False # 表示 pwm 极性 (normal/inversed) 8 | # enable = True # 表示是否使能 pwm 9 | 10 | try: 11 | pwm6 = pwm.PWM(6) 12 | pwm6.export() 13 | pwm6.period = 25000000 # 表示 pwm 的周期,单位 ns 14 | pwm6.duty_cycle = 100 # 表示占空比,单位 ns 15 | pwm6.enable = True # 表示是否使能 pwm 16 | for t in range (3): 17 | for i in range(0, 25000000, +1000000): 18 | pwm6.duty_cycle = i 19 | time.sleep(0.05) 20 | for i in range(25000000, 0, -1000000): 21 | pwm6.duty_cycle = i 22 | time.sleep(0.05) 23 | finally: 24 | pwm6.unexport() 25 | 26 | with pwm.PWM(6) as pwm6: 27 | pwm6.period = 25000000 # 表示 pwm 的周期,单位 ns 28 | pwm6.duty_cycle = 100 # 表示占空比,单位 ns 29 | pwm6.enable = True # 表示是否使能 pwm 30 | for t in range (3): 31 | for i in range(0, 25000000, +1000000): 32 | pwm6.duty_cycle = i 33 | time.sleep(0.05) 34 | for i in range(25000000, 0, -1000000): 35 | pwm6.duty_cycle = i 36 | time.sleep(0.05) 37 | -------------------------------------------------------------------------------- /ext_modules/_maix_camera/include/_maix_camera.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIX_CAMERA_H 2 | #define _MAIX_CAMERA_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #ifdef __cplusplus 14 | extern "C" 15 | { 16 | #endif 17 | #include "libmaix_cam.h" 18 | #include "libmaix_image.h" 19 | #define debug_line // printf("%s:%d %s %s %s \r\n", __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__) 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | 25 | #define R329Camera 26 | // #define V83xCamera 27 | 28 | #if !defined (R329Camera) && !defined (V83xCamera) 29 | #define VirtualCamera 30 | #endif 31 | 32 | class _camera 33 | { 34 | private: 35 | public: 36 | int width, height, dev_id, m, f; 37 | _camera(int w, int h, int dev_id, int m, int f); 38 | ~_camera(); 39 | pybind11::list read(); 40 | void close(); 41 | void __enter__(); 42 | void __exit__(); 43 | 44 | libmaix_cam_t *cam; 45 | libmaix_image_t *rgb_img; 46 | }; 47 | 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Amaork 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/test_maix_image.py: -------------------------------------------------------------------------------- 1 | 2 | from maix import display, camera, image 3 | from PIL import ImageDraw 4 | import time 5 | 6 | 7 | def show_run_time(func): 8 | import timeit 9 | 10 | def time_get(): 11 | elapsed_time = timeit.timeit(stmt=func, number=1) 12 | print(func, elapsed_time) 13 | return time_get 14 | 15 | 16 | @show_run_time 17 | def test_null(): 18 | img = camera.read() 19 | display.show(img) 20 | 21 | 22 | # 0.00949729199999183 23 | test_null() 24 | 25 | 26 | @show_run_time 27 | def test_maix(): 28 | img = camera.capture() 29 | img.draw_string(10, 10, u'time:%s' % time.time(), 30 | 1, color=(255, 0, 0), thickness=1) 31 | display.show(img) 32 | 33 | 34 | # 0.012572958999953698 35 | test_maix() 36 | 37 | 38 | @show_run_time 39 | def test_pil(): 40 | img = camera.camera.old_capture() 41 | draw = ImageDraw.Draw(img) 42 | draw.text((10, 10), u'time:%s' % time.time(), (255, 0, 0)) 43 | display.show(img) 44 | 45 | 46 | # 0.03788966700005858 47 | test_pil() 48 | -------------------------------------------------------------------------------- /ext_modules/_maix_display/example/pyav2pyaudio&display.py: -------------------------------------------------------------------------------- 1 | import pyaudio 2 | from maix import display, camera 3 | import av 4 | 5 | display.show(camera.capture()) 6 | 7 | try: 8 | # recommend flv 9 | # ffmpeg -r 30 -i bad_apple.mp4 -s 240x240 output.mp4 10 | # adb push ./output.mp4 /mnt/UDISK/ 11 | # adb push ./test.py / && adb shell 'python ./test.py' 12 | path_to_video = '/mnt/UDISK/output.mp4' 13 | container = av.open(path_to_video) 14 | ai_stream = container.streams.audio[0] 15 | vi_stream = container.streams.video[0] 16 | fifo = av.AudioFifo() 17 | p = pyaudio.PyAudio() 18 | ao = p.open(format=pyaudio.paFloat32, channels=2, rate=22050, output=True) 19 | for frame in container.decode(video=0, audio=0): 20 | if 'Audio' in repr(frame): 21 | frame.pts = None 22 | fifo.write(frame) 23 | for frame in fifo.read_many(4096): 24 | ao.write(frame.planes[0].to_bytes()) 25 | if 'Video' in repr(frame): 26 | display.show(bytes(frame.to_rgb().planes[0])) 27 | except Exception as e: 28 | print(e) 29 | finally: 30 | ao.stop_stream() 31 | ao.close() 32 | p.terminate() 33 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_image_draw_base.py: -------------------------------------------------------------------------------- 1 | from maix import Image 2 | import time 3 | import gc 4 | 5 | import signal 6 | def handle_signal_z(signum, frame): 7 | print("APP OVER") 8 | exit(0) 9 | signal.signal(signal.SIGINT, handle_signal_z) 10 | 11 | while True: 12 | img = Image.new(size=(240,240),color = (255,0,0),mode = "RGB") 13 | #写字 14 | img.draw_string(10,200,"hello word!",(0,0,255),1) 15 | img.show() 16 | time.sleep(1) 17 | #画线 18 | img.draw_line(10,10,10,100,color=(0,255,0),thickness = 1) 19 | img.show() 20 | time.sleep(1) 21 | #画框 22 | img.draw_rectangle(20,20,50,50,color=(0,255,0),thickness = 1) 23 | img.show() 24 | time.sleep(1) 25 | #画圆 26 | img.draw_circle(100,100,20,color=(0,255,0),thickness = 1) 27 | img.show() 28 | time.sleep(1) 29 | #画椭圆 30 | img.draw_ellipse(150,150,20,50,90,0,360,color=(0,255,0),thickness = 1) 31 | img.show() 32 | time.sleep(1) 33 | 34 | 35 | # while True: 36 | # img = _maix_image.new(size=(240,240),color = (255,0,0),mode = "RGB") 37 | # img.draw_string(10,200,"hello word!",(0,0,255),1) 38 | # img.show() 39 | # img.clear() 40 | # gc.collect() -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/test_load_forward_sobel_edge.py: -------------------------------------------------------------------------------- 1 | from maix import nn 2 | from PIL import Image, ImageDraw 3 | from maix import camera, display 4 | import numpy as np 5 | import time 6 | 7 | model = { 8 | "param": "/models/sobel_int8.param", 9 | "bin": "/models/sobel_int8.bin" 10 | } 11 | 12 | input_size = (224, 224, 3) 13 | output_size = (222, 222, 3) 14 | 15 | options = { 16 | "model_type": "awnn", 17 | "inputs": { 18 | "input0": input_size 19 | }, 20 | "outputs": { 21 | "output0": output_size 22 | }, 23 | "mean": [127.5, 127.5, 127.5], 24 | "norm": [0.0078125, 0.0078125, 0.0078125], 25 | } 26 | 27 | from PIL import Image 28 | 29 | m = nn.load(model, opt=options) 30 | 31 | while 1: 32 | # tmp = camera.read() 33 | # if len(tmp): 34 | # img = Image.frombytes("RGB", (224, 224), tmp) 35 | # img.save("img.jpg") 36 | img = camera.capture().resize(size=input_size[:2]) 37 | if img: 38 | # img.save("img.jpg") 39 | out = m.forward(img, quantize=True) 40 | out = out.astype(np.float32).reshape(output_size) 41 | out = (np.abs(out) * 255 / out.max()).astype(np.uint8) 42 | img2 = Image.fromarray(out, mode="RGB") 43 | # img2.save("img2.jpg") 44 | display.show(img2) 45 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/load_forward_sobel_edge.py: -------------------------------------------------------------------------------- 1 | from maix import nn 2 | from PIL import Image, ImageDraw 3 | import numpy as np 4 | import time 5 | 6 | test_jpg = "/root/input.jpg" 7 | model = { 8 | "param": "/root/models/sobel_int8.param", 9 | "bin": "/root/models/sobel_int8.bin" 10 | } 11 | 12 | input_size = (224, 224, 3) 13 | output_size = (222, 222, 3) 14 | 15 | options = { 16 | "model_type": "awnn", 17 | "inputs": { 18 | "input0": input_size 19 | }, 20 | "outputs": { 21 | "output0": output_size 22 | }, 23 | "mean": [127.5, 127.5, 127.5], 24 | "norm": [0.0078125, 0.0078125, 0.0078125], 25 | } 26 | print("-- load model:", model) 27 | m = nn.load(model, opt=options) 28 | print("-- load ok") 29 | 30 | print("-- read image") 31 | img = Image.open(test_jpg).resize(input_size[:2]) 32 | img.show() 33 | 34 | print("-- read image ok") 35 | print("-- forward model with image as input") 36 | out = m.forward(img, quantize=True, layout="hwc") 37 | # print("-- read image ok") 38 | # out = out.reshape(222, 222, 3) 39 | print("-- out:", out.shape, out.dtype) 40 | out = out.astype(np.float32).reshape(output_size) 41 | out = (np.abs(out) * 255 / out.max()).astype(np.uint8) 42 | img2 = Image.fromarray(out, mode="RGB") 43 | 44 | img2.show() 45 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_functional/src/py_maix_nn_function.cpp: -------------------------------------------------------------------------------- 1 | #include "py_maix_nn_function.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "libmaix_nn.h" 14 | #include "string.h" 15 | #include "mud.h" 16 | #include 17 | 18 | #define debug_line printf("%s:%d %s %s %s \r\n", __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__) 19 | 20 | namespace py = pybind11; 21 | 22 | class _Function 23 | { 24 | private: 25 | public: 26 | _Function(); 27 | ~_Function(); 28 | py::object softmax (py::object o_input , int dim); 29 | }; 30 | 31 | py::object _Function::softmax (py::object o_input , int dim) 32 | { 33 | if(dim >= 0) 34 | { 35 | std::cout <<"not support dim arg yet" << std::endl; 36 | return py::none(); 37 | } 38 | auto numpy_object_num =py::module::import("numpy").attr("ndarray"); 39 | if(py::isinstance(o_input)) 40 | { 41 | 42 | } 43 | else 44 | { 45 | std::cout << "only support numpy object" << std::endl; 46 | return py::none(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /envs/utils.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import time 4 | def get_incs(path, exclude=[]): 5 | setup_path = os.path.dirname(os.path.abspath(__file__)) + '/../' # envs/ 6 | return setup_path + path 7 | 8 | def get_srcs(path, file_type=['c', 'cpp', 'cc', 'cxx', 's'], exclude=[]): 9 | _sources = [] 10 | setup_path = os.path.dirname(os.path.abspath(__file__)) + '/../' # envs/ 11 | # print(setup_path + path) 12 | for root, dirs, files in os.walk(setup_path + path): 13 | for file in files: 14 | _type = file.split(".") 15 | if len(_type) > 1 and _type[1].lower() in file_type: 16 | abs_path = root.replace(setup_path, '') 17 | _sources.append(abs_path + '/' + file) 18 | elif file in file_type: 19 | abs_path = root.replace(setup_path, '') 20 | _sources.append(abs_path + '/' + file) 21 | if len(exclude): 22 | # _sources = list(set(_sources).difference(set(exclude))) 23 | # print('_sources', len(_sources)) 24 | for s in range(len(_sources)-1, -1, -1): 25 | for e in exclude: 26 | if e in _sources[s]: 27 | _sources.pop(s) 28 | break 29 | # else: 30 | # print(_sources[s]) 31 | # print('res', _sources) 32 | return _sources 33 | -------------------------------------------------------------------------------- /tests/general/uasge_evdev.py: -------------------------------------------------------------------------------- 1 | from maix import event, display, image 2 | from select import select 3 | import os 4 | os.system("insmod /lib/modules/4.9.118/cst816.ko") 5 | dev = event.InputDevice("/dev/input/event1") 6 | img = display.as_image() 7 | while True: 8 | display.show(img) 9 | r, w, x = select([dev], [], [], 0) # if r == 0 or set 0 will read() raise BlockingIOError 10 | if r: 11 | x, y, e = 0, 0, 0 12 | for data in dev.read(): 13 | if (data.type == 0x03): 14 | # print(' type: ', data.type, ' code: ', hex(data.code), ' value: ', hex(data.value)) 15 | if data.code == 0x35: # ABS_MT_POSITION_X 16 | x = data.value 17 | if data.code == 0x36: # ABS_MT_POSITION_Y 18 | y = data.value 19 | if data.code == 0x30: # ABS_MT_TOUCH_MAJOR 20 | e = data.value 21 | if data.code == 0x32: # ABS_MT_WIDTH_MAJOR 22 | if data.value == 0: 23 | img.draw_rectangle(0, 0, 240, 240, color=(0, 0, 0), thickness=-1) 24 | else: 25 | img.draw_circle(x, y, 2, color=(255, 0, 0), thickness=-1) 26 | tmp = "(%d, %d, %d, %s)" % (data.value, x, y, hex(e)) 27 | w, h = image.get_string_size(tmp) 28 | bak = image.new(size=(w + 20, h + 2)) 29 | bak.draw_string(0, 0, tmp) 30 | img.draw_image(bak, 120 - w // 2, 120) 31 | 32 | -------------------------------------------------------------------------------- /ext_modules/libi2c/Makefile: -------------------------------------------------------------------------------- 1 | PYTHON = python3 2 | CC = $(CROSS)gcc 3 | AR = $(CROSS)ar 4 | CFLAGS = -Wall -g -fPIC 5 | LDSHFLAGS = -rdynamic -shared 6 | ARFLAGS = rcv 7 | CODE_STYLE = astyle --align-pointer=name --align-reference=name --suffix=none --break-blocks --pad-oper --pad-header --break-blocks --keep-one-line-blocks --indent-switches --indent=spaces 8 | 9 | SOURCES=$(filter-out src/pyi2c.c, $(wildcard src/*.c)) 10 | HEADERS=$(wildcard src/*.h) 11 | OBJECTS=$(SOURCES:.c=.o) 12 | TARGETS = libi2c.a libi2c.so pylibi2c.so 13 | 14 | .PHONY:all clean example test install help style 15 | .SILENT: clean 16 | 17 | all:$(TARGETS) example 18 | 19 | clean: 20 | make -C example clean 21 | find . -name "*.o" | xargs rm -f 22 | $(RM) *.o *.so *~ a.out depend $(TARGETS) build -rf 23 | 24 | help: 25 | $(PYTHON) help.py 26 | 27 | test: 28 | $(PYTHON) -m unittest discover tests 29 | 30 | style: 31 | @find -regex '.*/.*\.\(c\|cpp\|h\)$$' | xargs $(CODE_STYLE) 32 | 33 | install: 34 | $(PYTHON) setup.py install 35 | 36 | example:$(TARGETS) 37 | make -C $@ 38 | 39 | libi2c.a:$(OBJECTS) 40 | $(AR) $(ARFLAGS) $@ $^ 41 | 42 | libi2c.so:$(OBJECTS) 43 | $(CC) $(LDSHFLAGS) -o $@ $^ 44 | 45 | pylibi2c.so:$(OBJECTS) 46 | $(PYTHON) setup.py build_ext --inplace 47 | 48 | depend:$(SOURCES) $(HEADERS) src/pyi2c.c 49 | $(CC) $(CFLAGS) -MM $^ > $@ 50 | 51 | -include depend 52 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_functional/include/py_maix_nn_function.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static void maix_nn_functional_softmax_float32(float *data, int n, float *out, int stride) 5 | { 6 | int i; 7 | float sum = 0; 8 | float largest_i = data[0]; 9 | if(!out) 10 | { 11 | out = data; 12 | } 13 | 14 | for (i = 0; i < n; ++i) 15 | { 16 | if (data[i * stride] > largest_i) 17 | largest_i = data[i * stride]; 18 | } 19 | for (i = 0; i < n; ++i) 20 | { 21 | float value = expf(data[i * stride] - largest_i); 22 | sum += value; 23 | out[i * stride] = value; 24 | } 25 | for (i = 0; i < n; ++i) 26 | { 27 | out[i * stride] /= sum; 28 | } 29 | } 30 | 31 | static void maix_nn_functional_softmax_double(double *data, int n, double *out, int stride) 32 | { 33 | int i; 34 | double sum = 0; 35 | double largest_i = data[0]; 36 | if(!out) 37 | { 38 | out = data; 39 | } 40 | 41 | for (i = 0; i < n; ++i) 42 | { 43 | if (data[i * stride] > largest_i) 44 | largest_i = data[i * stride]; 45 | } 46 | for (i = 0; i < n; ++i) 47 | { 48 | double value = expf(data[i * stride] - largest_i); 49 | sum += value; 50 | out[i * stride] = value; 51 | } 52 | for (i = 0; i < n; ++i) 53 | { 54 | out[i * stride] /= sum; 55 | } 56 | } -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/load_forward_camera.py: -------------------------------------------------------------------------------- 1 | from maix import nn 2 | from PIL import Image, ImageDraw 3 | from maix import camera, display 4 | 5 | test_jpg = "/root/test_input/input.jpg" 6 | model = { 7 | "param": "/root/models/resnet_awnn.param", 8 | "bin": "/root/models/resnet_awnn.bin" 9 | } 10 | 11 | options = { 12 | "model_type": "awnn", 13 | "inputs": { 14 | "input0": (224, 224, 3) 15 | }, 16 | "outputs": { 17 | "output0": (1, 1, 1000) 18 | }, 19 | "first_layer_conv_no_pad": False, 20 | "mean": [127.5, 127.5, 127.5], 21 | "norm": [0.00784313725490196, 0.00784313725490196, 0.00784313725490196], 22 | } 23 | print("-- load model:", model) 24 | m = nn.load(model, opt=options) 25 | print("-- load ok") 26 | 27 | print("-- read image") 28 | img = Image.open(test_jpg) 29 | print("-- read image ok") 30 | print("-- forward model with image as input") 31 | out = m.forward(img, quantize=True) 32 | print("-- read image ok") 33 | print("-- out:", out.shape) 34 | out = nn.F.softmax(out) 35 | print(out.max(), out.argmax()) 36 | 37 | from classes_label import labels 38 | while 1: 39 | img = camera.capture().resize(size=(224, 224)) 40 | out = m.forward(img, quantize=True) 41 | out = nn.F.softmax(out) 42 | msg = "{:.2f}: {}".format(out.max(), labels[out.argmax()]) 43 | print(msg) 44 | draw = ImageDraw.Draw(img) 45 | draw.text((0, 0), msg, fill=(255, 0, 0)) 46 | display.show(img) 47 | 48 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/load_forward_sobel_edge_camera.py: -------------------------------------------------------------------------------- 1 | 2 | class Edge: 3 | path = { 4 | # "param": "/root/models/sobel_int8.param", 5 | # "bin": "/root/models/sobel_int8.bin" 6 | "bin": "/root/models/aipu_sobel.bin" 7 | } 8 | 9 | input_size = (224,224,3) 10 | output_size = (224,224,3) 11 | 12 | options = { 13 | "model_type": "aipu", 14 | "inputs": { 15 | "input0": input_size 16 | }, 17 | "outputs": { 18 | "output0": output_size 19 | }, 20 | "mean": [127.5, 127.5, 127.5], 21 | "norm": [0.0078125, 0.0078125, 0.0078125], 22 | "scale":[0.15196067], 23 | } 24 | 25 | def __init__(self) -> None: 26 | from maix import nn 27 | print(" - - load model :",self.path) 28 | self.model = nn.load(self.path , opt = self.options) 29 | print("- -load ok") 30 | 31 | def __del__(self): 32 | del self.model 33 | 34 | 35 | #main 36 | from maix import display, camera 37 | import numpy as np 38 | global m 39 | m =Edge() 40 | 41 | #loop 42 | while True: 43 | img = camera.capture().resize(size=(224, 224)) 44 | out = m.model.forward(img, quantize=True, layout="hwc") 45 | out = out.astype(np.float32).reshape(m.output_size) 46 | out = (np.ndarray.__abs__(out) * 255 / out.max()).astype(np.uint8) 47 | data = out.tobytes() 48 | img2 = img.load(data,(222, 222), mode="RGB") 49 | display.show(img2) -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/r329_sobel.py: -------------------------------------------------------------------------------- 1 | 2 | class Edge: 3 | path = { 4 | # "param": "/root/models/sobel_int8.param", 5 | # "bin": "/root/models/sobel_int8.bin" 6 | "bin": "/root/models/aipu_sobel.bin" 7 | } 8 | 9 | input_size = (224,224,3) 10 | output_size = (224,224,3) 11 | 12 | options = { 13 | "model_type": "aipu", 14 | "inputs": { 15 | "input0": input_size 16 | }, 17 | "outputs": { 18 | "output0": output_size 19 | }, 20 | "mean": [127.5, 127.5, 127.5], 21 | "norm": [0.0078125, 0.0078125, 0.0078125], 22 | "scale":[0.15196067], # R329 有此选项,V831没有这个选项 23 | } 24 | 25 | def __init__(self) -> None: 26 | from maix import nn 27 | print(" - - load model :",self.path) 28 | self.model = nn.load(self.path , opt = self.options) 29 | print("- -load ok") 30 | 31 | def __del__(self): 32 | del self.model 33 | 34 | 35 | #main 36 | from maix import display, camera 37 | import numpy as np 38 | global m 39 | m =Edge() 40 | 41 | #loop 42 | while True: 43 | img = camera.capture().resize(size=(224, 224)) 44 | out = m.model.forward(img, quantize=True, layout="hwc") 45 | out = out.astype(np.float32).reshape(m.output_size) 46 | out = (np.ndarray.__abs__(out) * 255 / out.max()).astype(np.uint8) 47 | data = out.tobytes() 48 | img2 = img.load(data,(222, 222), mode="RGB") 49 | display.show(img2) -------------------------------------------------------------------------------- /tests/general/usage_desktop.py: -------------------------------------------------------------------------------- 1 | from maix import camera, display 2 | 3 | camera.config(size=(240, 240)) 4 | img = camera.capture() 5 | print(img) 6 | img.save("240x240.jpg") 7 | display.show(img) 8 | 9 | camera.config(size=(320, 240)) 10 | img = camera.capture() 11 | print(img) 12 | img.save("320x240.jpg") 13 | display.show(img) 14 | 15 | for i in range(10): 16 | camera.config(size=(240, 240)) 17 | for i in range(10): 18 | img = camera.capture() 19 | display.show(img) 20 | camera.config(size=(320, 240)) 21 | for i in range(10): 22 | img = camera.capture() 23 | display.show(img) 24 | 25 | display.config((416, 416)) 26 | # camera.config is remove. 27 | camera.camera.config((640, 480), 0, 1, 0) 28 | 29 | # while True: 30 | # t = camera.capture() 31 | # print(t) 32 | # print(type(t)) 33 | # display.show(t) 34 | 35 | from maix import camera, display 36 | t = camera.capture() 37 | print(t) 38 | print(type(t)) 39 | display.show(t) 40 | 41 | camera.camera.config((640, 480)) 42 | t = camera.capture() 43 | print(t) 44 | print(type(t)) 45 | display.show(t) 46 | 47 | from maix import camera, display 48 | t = camera.capture().draw_rectangle(30, 50, 130, 140, color=(255, 50, 50), thickness=-1) 49 | 50 | print(len(t.tobytes())) 51 | 52 | with open("t.bmp", "wb") as f: 53 | f.write(t.tobytes("bmp")) 54 | 55 | with open("t.jpg", "wb") as f: 56 | f.write(t.tobytes("jpg")) 57 | 58 | with open("t.png", "wb") as f: 59 | f.write(t.tobytes("png", (16, 3))) 60 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/r329_mobilenet2.py: -------------------------------------------------------------------------------- 1 | class MobileNetv2: 2 | path = { 3 | #R329 4 | "bin": "./models/aipu_mobilenet2.bin" 5 | 6 | # V831 7 | # "bin": "./models/awnn_mobilenet2.bin" 8 | # "param": "./models/awnn_mobilenet2.param" 9 | } 10 | input_size = (224,224,3) 11 | output_size = (1, 1, 1000) 12 | 13 | options = { 14 | # R329 15 | "model_type": "aipu", 16 | #V831 17 | # "model_type": "awnn" 18 | 19 | "inputs": { 20 | "input0": input_size 21 | }, 22 | "outputs": { 23 | "output0": output_size 24 | }, 25 | "mean": [127.5, 127.5, 127.5], 26 | "norm": [0.0078125, 0.0078125, 0.0078125], 27 | "scale":[0.15196067], # R329 有此选项,V831没有这个选项 28 | } 29 | 30 | def __init__(self) -> None: 31 | from maix import nn 32 | print(" - - load model :",self.path) 33 | self.model = nn.load(self.path , opt = self.options) 34 | print("- -load ok") 35 | 36 | def __del__(self): 37 | del self.model 38 | 39 | #main 40 | from classes_label import labels 41 | from maix import display, camera 42 | import numpy as np 43 | from maix import nn 44 | global m 45 | m = MobileNetv2() 46 | while True: 47 | img = camera.capture().resize(size=(224,224)) 48 | out = m.model.forward(img, quantize=True, layout="hwc") 49 | out2 = nn.F.softmax(out) 50 | msg = "{:.2f}: {}".format(out2.max(), labels[out.argmax()]) 51 | img.draw_string(0,0,msg,scale = 0.5 , color = (183,127,221)) 52 | display.show(img) -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/r329_resnet50.py: -------------------------------------------------------------------------------- 1 | 2 | class MobileNetv2: 3 | path = { 4 | #R329 5 | "bin": "./models/aipu_resnet50.bin" 6 | 7 | # V831 8 | # "bin": "./models/awnn_resnet50.bin" 9 | # "param": "./models/awnn_resnet50.param" 10 | } 11 | input_size = (224,224,3) 12 | output_size = (1, 1, 1000) 13 | 14 | options = { 15 | # R329 16 | "model_type": "aipu", 17 | #V831 18 | # "model_type": "awnn" 19 | 20 | "inputs": { 21 | "input0": input_size 22 | }, 23 | "outputs": { 24 | "output0": output_size 25 | }, 26 | "mean": [127.5, 127.5, 127.5], 27 | "norm": [0.0078125, 0.0078125, 0.0078125], 28 | "scale":[7.539542], # R329 有此选项,V831没有这个选项 29 | } 30 | 31 | def __init__(self) -> None: 32 | from maix import nn 33 | print(" - - load model :",self.path) 34 | self.model = nn.load(self.path , opt = self.options) 35 | print("- -load ok") 36 | 37 | def __del__(self): 38 | del self.model 39 | 40 | #main 41 | from classes_label import labels 42 | from maix import display, camera 43 | import numpy as np 44 | from maix import nn 45 | m = MobileNetv2() 46 | 47 | #loop 48 | while True: 49 | img = camera.capture().resize(size=(224, 224)) 50 | out = m.model.forward(img, quantize=True, layout="hwc") 51 | out2 = nn.F.softmax(out) 52 | msg = "{:.2f}: {}".format(out2.max(), labels[out.argmax()]) 53 | img.draw_string(0,0,msg,scale = 0.5 , color = (183,127,221)) 54 | display.show(img) -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/r329_shufflenet.py: -------------------------------------------------------------------------------- 1 | 2 | class MobileNetv2: 3 | path = { 4 | #R329 5 | "bin": "./models/aipu_shufflenet.bin" 6 | 7 | # V831 8 | # "bin": "./models/awnn_shufflenet.bin" 9 | # "param": "./models/awnn_shufflenet.param" 10 | } 11 | input_size = (224,224,3) 12 | output_size = (1, 1, 1000) 13 | 14 | options = { 15 | # R329 16 | "model_type": "aipu", 17 | #V831 18 | # "model_type": "awnn" 19 | 20 | "inputs": { 21 | "input0": input_size 22 | }, 23 | "outputs": { 24 | "output0": output_size 25 | }, 26 | "mean": [127.5, 127.5, 127.5], 27 | "norm": [0.0078125, 0.0078125, 0.0078125], 28 | "scale":[11.349483], # R329 有此选项,V831没有这个选项 29 | } 30 | 31 | def __init__(self) -> None: 32 | from maix import nn 33 | print(" - - load model :",self.path) 34 | self.model = nn.load(self.path , opt = self.options) 35 | print("- -load ok") 36 | 37 | def __del__(self): 38 | del self.model 39 | 40 | #main 41 | from classes_label import labels 42 | from maix import display, camera 43 | import numpy as np 44 | from maix import nn 45 | m = MobileNetv2() 46 | 47 | #loop 48 | while True: 49 | img = camera.capture().resize(size=(224, 224)) 50 | out = m.model.forward(img, quantize=True, layout="hwc") 51 | out2 = nn.F.softmax(out) 52 | msg = "{:.2f}: {}".format(out2.max(), labels[out.argmax()]) 53 | img.draw_string(0,0,msg,scale = 0.5 , color = (183,127,221)) 54 | display.show(img) 55 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/include/py_maix_nn.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPY_MAIX_NN_H_ 2 | #define _CPY_MAIX_NN_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "libmaix_nn.h" 10 | 11 | ///////////////////////////// 12 | #define _MAIX_NN_VERSION_ "0.2.0" 13 | #define _MAIX_NN_NAME_ "_maix_nn" 14 | PyDoc_STRVAR(_maix_nn_doc, "MaixPy Python3 nn(neural network) module.\n"); 15 | PyDoc_STRVAR(_maix_nn_functional_doc, "MaixPy Python3 nn(neural network) functional module.\n"); 16 | PyDoc_STRVAR(_maix_nn_decoder_doc, "MaixPy Python3 nn(neural network) decoder(post process) module.\n"); 17 | PyDoc_STRVAR(_maix_nn__app_doc, "MaixPy Python3 nn(neural network) _app module, please use app module instead.\n"); 18 | ///////////////////////////// 19 | 20 | PyDoc_STRVAR(maix_nn_model_type_name, "Model"); 21 | PyDoc_STRVAR(maix_nn_decoder_yolo2_type_name, "Yolo2"); 22 | PyDoc_STRVAR(maix_nn_app_classifier_type_name, "Classifier"); 23 | PyDoc_STRVAR(maix_nn_app_FaceRecognize_type_name, "FaceRecognize"); 24 | extern PyTypeObject PyMaix_NN_Model_Type; 25 | extern PyTypeObject PyMaix_NN_Decoder_Yolo2_Type; 26 | extern struct PyModuleDef maix_nn_functional_module; 27 | extern struct PyModuleDef maix_nn_decoder_module; 28 | extern struct PyModuleDef maix_nn_app_module; 29 | 30 | 31 | typedef struct 32 | { 33 | PyObject_HEAD; 34 | libmaix_nn_t* nn; 35 | int8_t* quantize_buffer; 36 | float** out_buffer; 37 | PyObject* inputs; 38 | PyObject* outputs; 39 | PyObject* m_numpy; 40 | int inputs_len; 41 | int outputs_len; 42 | bool is_init; 43 | } ModelObject; 44 | 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /ext_modules/_maix_speech/example/test_mic_input.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | root = os.getcwd() + "/" 4 | 5 | def unit_test(): 6 | # from maix import display, camera 7 | import time 8 | import _maix_speech 9 | asr = _maix_speech.Asr() 10 | # asr.open("hw:0,0", "/root/test_files/am_3332/am_3332_192") 11 | # asr.open("/root/test_files/1.2.wav", "/root/test_files/cnnctc/cnnctc_3332_192", 2) 12 | # asr.open("hw:0,0", "/root/test_files/cnnctc/cnnctc_3332_192") 13 | asr.open("hw:0,0", root + "aipu_l192_flow_66.bin") 14 | # asr.open("1.2.wav", root + "./aipu_l192_flow_66.bin") 15 | asr.clear() 16 | 17 | def asr_dig(info): 18 | print('asr_dig', info) 19 | asr.set_dig(640, asr_dig) 20 | 21 | keywords = [ 22 | ["qi1 ba1 jiu3", 0.1], 23 | ["yi1 nian2", 0.2], 24 | ["san1 si4 wu3", 0.3], 25 | ] 26 | similars = [ 27 | ["xiao3", "xiang3"], 28 | ["jing1", "xin1", "ting1", "jin1"], 29 | ] 30 | def asr_kws(keys): 31 | tmp = max(keys) 32 | print('asr_kws %s %s' % (keys.index(tmp), str(tmp))) 33 | asr.set_kws(keywords, similars, asr_kws) 34 | 35 | def asr_lvcsr(pnys, words): 36 | print('asr_lvcsr', pnys, words) 37 | asr.set_lvcsr( 38 | root + "lmS/lg_6m.sfst", 39 | root + "lmS/lg_6m.sym", 40 | root + "lmS/phones.bin", 41 | root + "lmS/words_utf.bin", 42 | 8.0, 10.0, 0.5, 0, asr_lvcsr) 43 | 44 | try: 45 | for i in range(10): 46 | # display.show(camera.capture()) 47 | # t.clear() 48 | asr.run() 49 | except Exception as e: 50 | print(e) 51 | # asr.set_dig(0, lambda:print('exit')) 52 | 53 | 54 | if __name__ == "__main__": 55 | 56 | unit_test() 57 | -------------------------------------------------------------------------------- /.github/workflows/maixpy3_build.yml: -------------------------------------------------------------------------------- 1 | name: maixpy3_build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | strategy: 10 | max-parallel: 4 11 | steps: 12 | - uses: actions/checkout@master 13 | - name: Get submodules 14 | run: | 15 | git submodule update --init --recursive 16 | - uses: actions/setup-python@v2 17 | with: 18 | python-version: 3.8 19 | - name: Install dependencies 20 | run: | 21 | sudo apt update 22 | sudo apt install libjpeg-dev gcc libopencv-dev -qq -y 23 | wget http://mirrors.kernel.org/ubuntu/pool/main/libf/libffi/libffi6_3.2.1-8_amd64.deb 24 | sudo apt install ./libffi6_3.2.1-8_amd64.deb -qq -y 25 | python3 -m pip install --upgrade pip 26 | python3 -m pip install pybind11 27 | wget https://github.com/sipeed/MaixPy3/releases/download/20211101/r329_linux_x86_python3.9_toolchain.zip 28 | unzip -q -o r329_linux_x86_python3.9_toolchain.zip -d /opt/ 29 | wget https://github.com/sipeed/MaixPy3/releases/download/20210613/v83x_linux_x86_python3.8_toolchain.zip 30 | unzip -q -o v83x_linux_x86_python3.8_toolchain.zip -d /opt/ 31 | - name: Test desktop build 32 | run: | 33 | python3 -m pip install . 34 | python3 setup.py sdist 35 | - name: Test maix_v83x build 36 | run: | 37 | source /opt/v83x_linux_x86_python3.8_toolchain/envsetup.sh 38 | python3.8 setup.py bdist_wheel maix_v83x 39 | - name: Test maix_r329 build 40 | run: | 41 | source /opt/r329_linux_x86_python3.9_toolchain/envsetup.sh 42 | python3.9 setup.py bdist_wheel maix_r329 43 | - name: Ready Publish distribution 📦 to PyPI 44 | run: | 45 | ls -l dist/* 46 | -------------------------------------------------------------------------------- /maix/gpio.py: -------------------------------------------------------------------------------- 1 | # https://pypi.org/project/gpiod/ 2 | 3 | try: 4 | from gpiod import chip, line, line_request 5 | config = None # rpi is default value A 0 6 | def gpio(gpio_line=0, gpio_bank="A", gpio_chip=0, line_mode = line_request.DIRECTION_OUTPUT): 7 | global config 8 | if config != None and gpio_line in config: 9 | gpio_bank, gpio_chip = config[gpio_line] 10 | l, c = [32 * (ord(gpio_bank.lower()[0]) - ord('a')) + gpio_line, chip("gpiochip%d" % gpio_chip)] 11 | tmp = c.get_line(l) 12 | cfg = line_request() # led.active_state == line.ACTIVE_LOW 13 | cfg.request_type = line_mode # line.DIRECTION_INPUT 14 | tmp.request(cfg) 15 | tmp.source = "GPIO chip %s bank %s line %d" % (gpio_chip, gpio_bank, gpio_line) 16 | return tmp 17 | def load(cfg=None): 18 | global config 19 | config = cfg 20 | except ModuleNotFoundError as e: 21 | pass 22 | 23 | m2dock = { 24 | 6 : ("H", 1), 25 | 7 : ("H", 1), 26 | 8 : ("H", 1), 27 | 13 : ("H", 1), 28 | 14 : ("H", 1), 29 | } 30 | 31 | rv11xx = { 32 | 0 : ("A", 4), 33 | 1 : ("A", 4), 34 | } 35 | 36 | if __name__ == '__main__': 37 | import time 38 | # from maix import gpio 39 | # gpio.load(m2dock) 40 | load(m2dock) 41 | led = gpio(6) 42 | print(led.source) 43 | for i in range(3): 44 | led.set_value(0) 45 | print(led.get_value()) 46 | time.sleep(0.5) 47 | led.set_value(1) 48 | print(led.get_value()) 49 | time.sleep(0.5) 50 | led.release() 51 | load(None) 52 | led = gpio(6, "H", 1) 53 | print(led.source) 54 | for i in range(3): 55 | led.set_value(0) 56 | print(led.get_value()) 57 | time.sleep(0.5) 58 | led.set_value(1) 59 | print(led.get_value()) 60 | time.sleep(0.5) 61 | led.release() 62 | 63 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_version_find_line.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # maix_vision.find_line()函数说明 3 | # 功能:在道路图片pic中寻找线 4 | # 返回值:字典类型,rect:矩形的四个顶点,pixels:矩形的面积,cx、cy:矩形的中心坐标,rotation:矩形的倾斜角 5 | #{'rect': [9, 229, 9, 9, 145, 9, 145, 229], 'pixels': 12959, 'cx': 77, 'cy': 119, 'rotation': -1.570796251296997} 6 | # 时间:2021年9月16日, 2021年11月16日更新 7 | # 作者:dianjixz 8 | from maix import image, display, camera 9 | import time 10 | 11 | 12 | class funation: 13 | def __init__(self, device=None): 14 | self.event = self.run 15 | 16 | def __del__(self): 17 | pass 18 | 19 | def run(self): 20 | tmp = camera.capture() 21 | t = time.time() 22 | ma = tmp.find_line() 23 | t = time.time() - t 24 | print("-- forward time: {}s".format(t)) 25 | # print(ma) 26 | tmp.draw_line(ma["rect"][0], ma["rect"][1], ma["rect"][2], 27 | ma["rect"][3], color=(255, 255, 255), thickness=1) 28 | tmp.draw_line(ma["rect"][2], ma["rect"][3], ma["rect"][4], 29 | ma["rect"][5], color=(255, 255, 255), thickness=1) 30 | tmp.draw_line(ma["rect"][4], ma["rect"][5], ma["rect"][6], 31 | ma["rect"][7], color=(255, 255, 255), thickness=1) 32 | tmp.draw_line(ma["rect"][6], ma["rect"][7], ma["rect"][0], 33 | ma["rect"][1], color=(255, 255, 255), thickness=1) 34 | tmp.draw_circle(ma["cx"], ma["cy"], 4, 35 | color=(255, 255, 255), thickness=1) 36 | display.show(tmp) 37 | 38 | 39 | if __name__ == "__main__": 40 | import signal 41 | 42 | def handle_signal_z(signum, frame): 43 | print("APP OVER") 44 | exit(0) 45 | signal.signal(signal.SIGINT, handle_signal_z) 46 | start = funation() 47 | while True: 48 | start.event() 49 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/include/py_maix_nn.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPY_MAIX_NN_H_ 2 | #define _CPY_MAIX_NN_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include "libmaix_nn.h" 10 | #include "mud.h" 11 | 12 | ///////////////////////////// 13 | #define _MAIX_NN_VERSION_ "0.2.0" 14 | #define _MAIX_NN_NAME_ "_maix_nn" 15 | PyDoc_STRVAR(_maix_nn_doc, "MaixPy Python3 nn(neural network) module.\n"); 16 | PyDoc_STRVAR(_maix_nn_functional_doc, "MaixPy Python3 nn(neural network) functional module.\n"); 17 | PyDoc_STRVAR(_maix_nn_decoder_doc, "MaixPy Python3 nn(neural network) decoder(post process) module.\n"); 18 | PyDoc_STRVAR(_maix_nn__app_doc, "MaixPy Python3 nn(neural network) _app module, please use app module instead.\n"); 19 | ///////////////////////////// 20 | 21 | PyDoc_STRVAR(maix_nn_model_type_name, "Model"); 22 | PyDoc_STRVAR(maix_nn_decoder_yolo2_type_name, "Yolo2"); 23 | PyDoc_STRVAR(maix_nn_app_classifier_type_name, "Classifier"); 24 | PyDoc_STRVAR(maix_nn_app_FaceRecognize_type_name, "FaceRecognize"); 25 | extern PyTypeObject PyMaix_NN_Model_Type; 26 | extern PyTypeObject PyMaix_NN_Decoder_Yolo2_Type; 27 | extern struct PyModuleDef maix_nn_functional_module; 28 | extern struct PyModuleDef maix_nn_decoder_module; 29 | extern struct PyModuleDef maix_nn_app_module; 30 | 31 | 32 | typedef struct 33 | { 34 | PyObject_HEAD; 35 | libmaix_nn_t* nn; 36 | int8_t* quantize_buffer; 37 | float** out_buffer; 38 | PyObject* inputs; 39 | PyObject* outputs; 40 | PyObject* m_numpy; 41 | int inputs_len; 42 | int outputs_len; 43 | bool is_init; 44 | char * mud; 45 | mud_info *info; 46 | bool use_mud; 47 | } ModelObject; 48 | 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /maix/event.py: -------------------------------------------------------------------------------- 1 | 2 | # https://python-evdev.readthedocs.io/ 3 | 4 | try: 5 | class LazyImport: 6 | def __init__(self, module_name): 7 | self.module_name = module_name 8 | self.module = None 9 | def __getattr__(self, name): 10 | if self.module is None: 11 | self.module = __import__(self.module_name) 12 | return getattr(self.module, name) 13 | # import asyncio 14 | asyncio = LazyImport("asyncio") # evdev will normal load asyncio > 5M 15 | from evdev import InputDevice 16 | except ModuleNotFoundError as e: 17 | pass 18 | 19 | if __name__ == '__main__': 20 | # from maix import event 21 | # event.InputDevice 22 | 23 | def check_key(default="/dev/input/event0"): 24 | import os 25 | tmp = "/dev/input/by-path/" 26 | if os.path.exists(tmp): 27 | for i in os.listdir(tmp): 28 | if i.find("kbd") != -1: 29 | return tmp + i 30 | return default 31 | 32 | def detectInputKey(count): 33 | from select import select 34 | dev = InputDevice(check_key()) 35 | while True: 36 | select([dev], [], []) 37 | for event in dev.read(): 38 | if event.value == 1 and event.code != 0: 39 | count += 1 40 | print(count) 41 | from selectors import DefaultSelector, EVENT_READ 42 | selector = DefaultSelector() 43 | mouse = InputDevice('/dev/input/event7') 44 | keybd = InputDevice('/dev/input/event13') 45 | # This works because InputDevice has a `fileno()` method. 46 | selector.register(mouse, EVENT_READ) 47 | selector.register(keybd, EVENT_READ) 48 | try: 49 | while True: 50 | for key, mask in selector.select(): 51 | device = key.fileobj 52 | for event in device.read(): 53 | print(event) 54 | except Exception as e: 55 | mouse.close() 56 | keybd.close() 57 | 58 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | setup.py file for maixpy3 5 | """ 6 | 7 | import sys, platform 8 | from setuptools import setup, find_packages 9 | 10 | ext_modules, data_files, py_modules = [], [], [] 11 | 12 | sysstr = platform.system() 13 | 14 | if (sysstr == "Windows"): 15 | from envs.windows import _maix_modules, _maix_data_files, _maix_py_modules 16 | elif (sysstr == "Linux"): 17 | if 'maix_v83x' in sys.argv: 18 | sys.argv.remove('maix_v83x') 19 | from envs.maix_v83x import _maix_modules, _maix_data_files, _maix_py_modules 20 | elif 'maix_r329' in sys.argv: 21 | from envs.maix_r329 import _maix_modules, _maix_data_files, _maix_py_modules 22 | sys.argv.remove('maix_r329') 23 | else: 24 | from envs.linux_desktop import _maix_modules, _maix_data_files, _maix_py_modules 25 | 26 | ext_modules.extend(_maix_modules) 27 | data_files.extend(_maix_data_files) 28 | py_modules.extend(_maix_py_modules) 29 | 30 | from maix import version 31 | 32 | setup( 33 | name='maixpy3', 34 | version=version, 35 | license='MIT', 36 | author='Sipeed', 37 | author_email="support@sipeed.com", 38 | url='https://github.com/sipeed/maixpy3', 39 | description="MaixPy Python3 library", 40 | long_description=open('README.md', 'r', encoding='UTF-8').read(), 41 | long_description_content_type='text/markdown', 42 | install_requires=py_modules, 43 | ext_modules=ext_modules, 44 | packages = find_packages( 45 | exclude=['envs'] # remove from build 46 | ), # find __init__.py packages 47 | classifiers=[ 48 | 'Programming Language :: Python :: 3', 49 | ], 50 | extras_require={"test": "pytest"}, 51 | entry_points={ 52 | "console_scripts": ["maixpy3_rpycs=maix.mjpg:start"] 53 | }, 54 | include_package_data=True, 55 | package_data = { 56 | '': ['*.so'], 57 | '': ['*.h'], 58 | }, 59 | data_files=data_files, 60 | ) 61 | -------------------------------------------------------------------------------- /docs/clear.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #coding=utf-8 3 | 4 | import os,sys 5 | from stat import * 6 | 7 | # Declares a collection of file suffix names(.xxx) to be deleted 8 | DelFiles=['pyc', 'log', 'o'] 9 | 10 | # Declares a collection of folder names that you want to delete 11 | DelFolders=['__pycache__', 'dist', 'build', 'MaixPy3.egg-info'] 12 | 13 | def PurgeCatalog(path): 14 | count = 0 15 | for item in os.listdir(path): 16 | subpath = os.path.join(path, item) 17 | mode = os.stat(subpath).st_mode 18 | if S_ISDIR(mode): 19 | count += PurgeCatalog(subpath) 20 | else: 21 | os.chmod(subpath, S_IREAD|S_IWRITE) 22 | os.unlink(subpath) 23 | count += 1 24 | os.rmdir(path) 25 | count += 1 26 | return count 27 | 28 | def ClearCatalog(path): 29 | for catalog in os.walk(path): 30 | print("find files : %s." % catalog[2]) 31 | for file_name in catalog[2]: 32 | if '.' in file_name: 33 | file_type = file_name.rsplit('.', 1)[1] 34 | if file_type in DelFiles: 35 | print('file %s deleted.' % (os.path.join(catalog[0], file_name))) 36 | os.remove(os.path.join(catalog[0], file_name)) 37 | print("find folders : %s." % catalog[1]) 38 | for file_folder in catalog[1]: 39 | print("into file_folder %s." % file_folder) 40 | if file_folder in DelFolders: 41 | print("file_folder %s deleted." % os.path.join(catalog[0], file_folder)) 42 | print("files %d deleted." % PurgeCatalog(os.path.join(catalog[0], file_folder))) 43 | 44 | if __name__ == '__main__': 45 | # python %cd%/Clear.py %cd% 46 | if len(sys.argv) != 2: 47 | print( 'please add argv path : %s ' % sys.argv[0]) # %cd% 48 | sys.exit(1) 49 | ClearCatalog(sys.argv[1]) -------------------------------------------------------------------------------- /tests/maix_v831/yolo2.py: -------------------------------------------------------------------------------- 1 | from maix import nn, camera, image, display 2 | from maix.nn import decoder 3 | import time 4 | 5 | model = { 6 | "param": "./yolo2_20class_awnn.param", 7 | "bin": "./yolo2_20class_awnn.bin" 8 | } 9 | options = { 10 | "model_type": "awnn", 11 | "inputs": { 12 | "input0": (224, 224, 3) 13 | }, 14 | "outputs": { 15 | "output0": (7, 7, (1+4+20)*5) 16 | }, 17 | "mean": [127.5, 127.5, 127.5], 18 | "norm": [0.0078125, 0.0078125, 0.0078125], 19 | } 20 | 21 | labels = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"] 22 | anchors = [5.4, 5.38, 1.65, 2.09, 0.8, 1.83, 2.45, 4.14, 0.46, 0.8] 23 | 24 | m = nn.load(model, opt=options) 25 | yolo2_decoder = decoder.Yolo2(len(labels), anchors, net_in_size=(options["inputs"]["input0"][0], options["inputs"]["input0"][1]), net_out_size=(7, 7)) 26 | 27 | while True: 28 | img = camera.capture() 29 | AI_img = img.copy().resize(224, 224) 30 | out = m.forward(AI_img.tobytes(), quantize=True, layout="hwc") 31 | boxes, probs = yolo2_decoder.run(out, nms=0.3, threshold=0.3, img_size=(options["inputs"]["input0"][0], options["inputs"]["input0"][1])) 32 | 33 | if len(boxes): 34 | for i, box in enumerate(boxes): 35 | class_id = probs[i][0] 36 | prob = probs[i][1][class_id] 37 | disp_str = "{}:{:.2f}%".format(labels[class_id], prob*100) 38 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3], color = (0, 255, 0), thickness=2) 39 | x = box[0] 40 | y = box[1] - 20 41 | if y < 0: 42 | y = 0 43 | img.draw_string(x, y, disp_str, 1.5, color = (255, 0, 0), thickness=2) 44 | 45 | display.show(img) 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/maixpy3_pypi.yml: -------------------------------------------------------------------------------- 1 | name: maixpy3_pypi 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: ubuntu-latest 11 | strategy: 12 | max-parallel: 4 13 | steps: 14 | - uses: actions/checkout@master 15 | - name: Get submodules 16 | run: | 17 | git submodule update --init --recursive 18 | - uses: actions/setup-python@v2 19 | with: 20 | python-version: 3.8 21 | - name: Install dependencies 22 | run: | 23 | sudo apt update 24 | sudo apt install libjpeg-dev gcc libopencv-dev -qq -y 25 | wget http://mirrors.kernel.org/ubuntu/pool/main/libf/libffi/libffi6_3.2.1-8_amd64.deb 26 | sudo apt install ./libffi6_3.2.1-8_amd64.deb -qq -y 27 | python3 -m pip install --upgrade pip 28 | python3 -m pip install pybind11 29 | wget https://github.com/sipeed/MaixPy3/releases/download/20211101/r329_linux_x86_python3.9_toolchain.zip 30 | unzip -q -o r329_linux_x86_python3.9_toolchain.zip -d /opt/ 31 | wget https://github.com/sipeed/MaixPy3/releases/download/20210613/v83x_linux_x86_python3.8_toolchain.zip 32 | unzip -q -o v83x_linux_x86_python3.8_toolchain.zip -d /opt/ 33 | - name: Test desktop build 34 | run: | 35 | python3 -m pip install . 36 | python3 setup.py sdist 37 | - name: Test maix_v83x build 38 | run: | 39 | source /opt/v83x_linux_x86_python3.8_toolchain/envsetup.sh 40 | python3.8 setup.py bdist_wheel maix_v83x 41 | - name: Test maix_r329 build 42 | run: | 43 | source /opt/r329_linux_x86_python3.9_toolchain/envsetup.sh 44 | python3.9 setup.py bdist_wheel maix_r329 45 | - name: Publish distribution 📦 to PyPI 46 | uses: pypa/gh-action-pypi-publish@master 47 | with: 48 | user: __token__ 49 | password: ${{ secrets.PYPI_API_TOKEN }} 50 | skip_existing: true -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/example/hand.py: -------------------------------------------------------------------------------- 1 | from time import time 2 | 3 | class Hnad: 4 | mdsc_path = "./v831_yolo_hand.mud" 5 | 6 | labels = ["0","1","2","3","4","5"] 7 | anchors = [3.78, 5.81, 3.97, 3.98, 4.05, 4.98, 4.81, 5.41, 2.91, 4.53] 8 | 9 | def __init__(self) -> None: 10 | 11 | from maix import nn 12 | self.model = nn.load(self.mdsc_path) 13 | from maix.nn import decoder 14 | self.decoder = decoder.Yolo2(len(self.labels) , self.anchors , net_in_size = (224, 224) ,net_out_size = (7,7)) 15 | 16 | def __del__(self): 17 | del self.model 18 | del self.decoder 19 | 20 | def cal_fps(self ,start , end): 21 | one_second = 1 22 | one_flash = end - start 23 | fps = one_second / one_flash 24 | return fps 25 | 26 | def draw_rectangle_with_title(self ,img, box, disp_str , fps ): 27 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3],color=(255, 0, 0), thickness=2) 28 | img.draw_string(box[0], box[1]+ box[3] ,disp_str, scale=0.5,color=(0, 0, 255), thickness=2) 29 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=2 ,color=(0, 0, 255), thickness=2) 30 | 31 | def process(self,input): 32 | t = time() 33 | out = self.model.forward(input, quantize=1, layout = "hwc") 34 | boxes, probs = self.decoder.run(out, nms=0.5, threshold=0.6, img_size=(224,224)) 35 | for i, box in enumerate(boxes): 36 | class_id = probs[i][0] 37 | prob = probs[i][1][class_id] 38 | disp_str = "{}:{:.2f}%".format(self.labels[class_id], prob*100) 39 | fps = self.cal_fps(t, time()) 40 | self.draw_rectangle_with_title(input, box, disp_str, fps) 41 | 42 | def main(): 43 | from maix import display, camera 44 | app = Hnad() 45 | while True: 46 | img = camera.capture().resize(size=(224,224)) 47 | app.process(img) 48 | display.show(img) 49 | 50 | main() -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/example/v831_yolo2_person_class_mdsc.py: -------------------------------------------------------------------------------- 1 | class Yolo: 2 | mdsc_path = "/root/mud/v831_yolo_person.mud" 3 | labels = ["person"] 4 | anchors = [4.72, 6.26, 1.39, 3.53, 0.78, 1.9, 0.35, 0.95, 2.49, 4.87] 5 | 6 | def __init__(self) -> None: 7 | from maix import nn 8 | print(" - - load model :",self.mdsc_path) 9 | # self.model = nn.load(self.model, opt=self.options) 10 | self.model = nn.load(self.mdsc_path) 11 | print("- -load ok") 12 | from maix.nn import decoder 13 | print("- - load decoder") 14 | self.decoder = decoder.Yolo2(len(self.labels) , self.anchors , net_in_size = (224, 224) ,net_out_size = (7,7)) 15 | print("-- decoder load done") 16 | 17 | def __del__(self): 18 | del self.model 19 | del self.decoder 20 | 21 | def cal_fps(self ,start , end): 22 | one_second = 1 23 | one_flash = end - start 24 | fps = one_second / one_flash 25 | return fps 26 | 27 | def draw_rectangle_with_title(self ,img, box, disp_str , fps ): 28 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3],color=(255, 0, 0), thickness=2) 29 | img.draw_string(box[0], box[1]+ box[3] ,disp_str, scale=0.5,color=(0, 0, 255), thickness=2) 30 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=2 ,color=(0, 0, 255), thickness=2) 31 | 32 | # maix 33 | from maix import display,camera 34 | import time 35 | global m 36 | m = Yolo() 37 | 38 | while True: 39 | img = camera.capture().resize(size=(224,224)) 40 | t = time.time() 41 | out = m.model.forward(img, quantize=1, layout = "hwc") 42 | boxes, probs = m.decoder.run(out, nms=0.5, threshold=0.4, img_size=(224,224)) 43 | for i, box in enumerate(boxes): 44 | class_id = probs[i][0] 45 | prob = probs[i][1][class_id] 46 | disp_str = "{}:{:.2f}%".format(m.labels[class_id], prob*100) 47 | fps = m.cal_fps(t, time.time()) 48 | m.draw_rectangle_with_title(img, box, disp_str, fps) 49 | display.show(img) -------------------------------------------------------------------------------- /ext_modules/_maix_speech/example/test_maix_speech.py: -------------------------------------------------------------------------------- 1 | 2 | def show_run_time(func): 3 | import timeit 4 | 5 | def time_get(): 6 | elapsed_time = timeit.timeit(stmt=func, number=1) 7 | print(func, elapsed_time) 8 | return time_get 9 | 10 | 11 | @show_run_time 12 | def code_unit_test(): 13 | import _maix_speech 14 | t = _maix_speech.Asr() 15 | t.open() 16 | t.clear() 17 | t.run() 18 | t.clear() 19 | t.exit() 20 | 21 | # unit_test() 22 | 23 | 24 | @show_run_time 25 | def unit_test(): 26 | # from maix import display, camera 27 | import time 28 | import _maix_speech 29 | asr = _maix_speech.Asr() 30 | # asr.open("hw:0,0", "/root/test_files/am_3332/am_3332_192") 31 | 32 | # asr.open("/root/test_files/1.2.wav", "/root/test_files/cnnctc/cnnctc_3332_192", 2) 33 | # asr.open("hw:0,0", "/root/test_files/cnnctc/cnnctc_3332_192") 34 | asr.open("hw:0,0", "/root/test_files/aipu_l192_flow_66.bin") 35 | asr.clear() 36 | 37 | def asr_dig(info): 38 | print('asr_dig', info) 39 | asr.set_dig(640, asr_dig) 40 | 41 | keywords = [ 42 | ["qi1 ba1 jiu3", 0.1], 43 | ["yi1 nian2", 0.2], 44 | ["san1 si4 wu3", 0.3], 45 | ] 46 | similars = [ 47 | ["xiao3", "xiang3"], 48 | ["jing1", "xin1", "ting1", "jin1"], 49 | ] 50 | def asr_kws(keys): 51 | tmp = max(keys) 52 | print('asr_kws %s %s' % (keys.index(tmp), str(tmp))) 53 | asr.set_kws(keywords, similars, asr_kws) 54 | 55 | def asr_lvcsr(pnys, words): 56 | print('asr_lvcsr', pnys, words) 57 | asr.set_lvcsr( 58 | "/root/test_files/lmS/lg_6m.sfst", 59 | "/root/test_files/lmS/lg_6m.sym", 60 | "/root/test_files/lmS/phones.bin", 61 | "/root/test_files/lmS/words_utf.bin", 62 | 8.0, 10.0, 0.5, 0, asr_lvcsr) 63 | 64 | for i in range(5): 65 | # display.show(camera.capture()) 66 | # t.clear() 67 | asr.run(1) 68 | 69 | # asr.set_dig(0, lambda:print('exit')) 70 | 71 | 72 | if __name__ == "__main__": 73 | 74 | unit_test() 75 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/example/mask.py: -------------------------------------------------------------------------------- 1 | 2 | from time import time 3 | class Mask: 4 | #mdsc_path 5 | # V831 6 | mdsc_path = "/root/mud/v831_yolo_mask.mud" 7 | #R329 8 | # mdsc_path = "/root/mud/r329_yolo_mask.mud" 9 | 10 | labels = ["no wear","wear"] 11 | anchors = [1.19, 1.98, 2.79, 4.59, 4.53, 8.92, 8.06, 5.29, 10.32, 10.65] 12 | 13 | def __init__(self) -> None: 14 | 15 | from maix import nn 16 | self.model = nn.load(self.mdsc_path) 17 | from maix.nn import decoder 18 | self.decoder = decoder.Yolo2(len(self.labels) , self.anchors , net_in_size = (224, 224) ,net_out_size = (7,7)) 19 | 20 | def __del__(self): 21 | del self.model 22 | del self.decoder 23 | 24 | def cal_fps(self ,start , end): 25 | one_second = 1 26 | one_flash = end - start 27 | fps = one_second / one_flash 28 | return fps 29 | 30 | def draw_rectangle_with_title(self ,img, box, disp_str , fps ): 31 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3],color=(255, 0, 0), thickness=2) 32 | img.draw_string(box[0], box[1]+ box[3] ,disp_str, scale=1,color=(0, 0, 255), thickness=1) 33 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=2 ,color=(0, 0, 255), thickness=1) 34 | 35 | def process(self,input): 36 | t = time() 37 | out = self.model.forward(input, quantize=1, layout = "hwc") 38 | boxes, probs = self.decoder.run(out, nms=0.5, threshold=0.6, img_size=(224,224)) 39 | for i, box in enumerate(boxes): 40 | class_id = probs[i][0] 41 | prob = probs[i][1][class_id] 42 | disp_str = "{}:{:.2f}%".format(self.labels[class_id], prob*100) 43 | fps = self.cal_fps(t, time()) 44 | self.draw_rectangle_with_title(input, box, disp_str, fps) 45 | 46 | def main(): 47 | from maix import display, camera 48 | app = Mask() 49 | 50 | while True: 51 | img = camera.capture().resize(size=(224, 224)) 52 | app.process(img) 53 | display.show(img) 54 | main() -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/example/person.py: -------------------------------------------------------------------------------- 1 | from time import time 2 | 3 | class Person: 4 | #mdsc_path 5 | # V831 6 | #mdsc_path = "/root/mud/v831_yolo_person.mud" 7 | #R329 8 | mdsc_path = "/root/mud/r329_yolo_person.mud" 9 | 10 | labels = ["person"] 11 | anchors = [4.72, 6.26, 1.39, 3.53, 0.78, 1.9, 0.35, 0.95, 2.49, 4.87] 12 | 13 | def __init__(self) -> None: 14 | 15 | from maix import nn 16 | self.model = nn.load(self.mdsc_path) 17 | from maix.nn import decoder 18 | self.decoder = decoder.Yolo2(len(self.labels) , self.anchors , net_in_size = (224, 224) ,net_out_size = (7,7)) 19 | 20 | def __del__(self): 21 | del self.model 22 | del self.decoder 23 | 24 | def cal_fps(self ,start , end): 25 | one_second = 1 26 | one_flash = end - start 27 | fps = one_second / one_flash 28 | return fps 29 | 30 | def draw_rectangle_with_title(self ,img, box, disp_str , fps ): 31 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3],color=(255, 0, 0), thickness=2) 32 | img.draw_string(box[0], box[1]+ box[3] ,disp_str, scale=0.5,color=(0, 0, 255), thickness=2) 33 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=2 ,color=(0, 0, 255), thickness=2) 34 | 35 | def process(self,input): 36 | t = time() 37 | out = self.model.forward(input, quantize=1, layout = "hwc") 38 | boxes, probs = self.decoder.run(out, nms=0.5, threshold=0.6, img_size=(224,224)) 39 | for i, box in enumerate(boxes): 40 | class_id = probs[i][0] 41 | prob = probs[i][1][class_id] 42 | disp_str = "{}:{:.2f}%".format(self.labels[class_id], prob*100) 43 | fps = self.cal_fps(t, time()) 44 | self.draw_rectangle_with_title(input, box, disp_str, fps) 45 | 46 | def main(): 47 | from maix import display, camera 48 | app = Person() 49 | 50 | while True: 51 | img = camera.capture().resize(size=(224,224)) 52 | app.process(img) 53 | display.show(img) 54 | 55 | main() -------------------------------------------------------------------------------- /tests/test_rpyc.py: -------------------------------------------------------------------------------- 1 | import os 2 | import rpyc 3 | import tempfile 4 | from rpyc.utils.server import ThreadedServer, ThreadPoolServer 5 | from rpyc import SlaveService 6 | import unittest 7 | 8 | 9 | class Test_ThreadedServer(unittest.TestCase): 10 | 11 | def setUp(self): 12 | self.server = ThreadedServer(SlaveService, port=18878, auto_register=False) 13 | self.server.logger.quiet = False 14 | self.server._start_in_thread() 15 | 16 | def tearDown(self): 17 | while self.server.clients: 18 | pass 19 | self.server.close() 20 | 21 | def test_connection(self): 22 | conn = rpyc.classic.connect("localhost", port=18878) 23 | print(conn.modules.sys) 24 | print(conn.modules["xml.dom.minidom"].parseString("")) 25 | conn.execute("x = 5") 26 | self.assertEqual(conn.namespace["x"], 5) 27 | self.assertEqual(conn.eval("1+x"), 6) 28 | conn.close() 29 | 30 | 31 | class Test_ThreadedServerOverUnixSocket(unittest.TestCase): 32 | 33 | def setUp(self): 34 | self.socket_path = tempfile.mktemp() 35 | self.server = ThreadedServer(SlaveService, socket_path=self.socket_path, auto_register=False) 36 | self.server.logger.quiet = False 37 | self.server._start_in_thread() 38 | 39 | def tearDown(self): 40 | self.server.close() 41 | os.remove(self.socket_path) 42 | 43 | def test_connection(self): 44 | c = rpyc.classic.unix_connect(self.socket_path) 45 | print(c.modules.sys) 46 | print(c.modules["xml.dom.minidom"].parseString("")) 47 | c.execute("x = 5") 48 | self.assertEqual(c.namespace["x"], 5) 49 | self.assertEqual(c.eval("1+x"), 6) 50 | c.close() 51 | 52 | 53 | class Test_ThreadPoolServer(Test_ThreadedServer): 54 | 55 | def setUp(self): 56 | self.server = ThreadPoolServer(SlaveService, port=18878, auto_register=False) 57 | self.server.logger.quiet = False 58 | self.server._start_in_thread() 59 | 60 | 61 | if __name__ == "__main__": 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /maix/display.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | _width, _height, __mode__ = 240, 240, "RGB" 4 | 5 | def config(size=(240, 240)): 6 | global _width, _height 7 | if size[0] > 0 and size[1] > 0: 8 | _width, _height = size[0], size[1] 9 | 10 | try: 11 | __show__ = None 12 | from _maix_display import Display 13 | __show__ = Display() 14 | config(size=(__show__.width, __show__.height)) 15 | def __draw__(img): 16 | global __show__, _width, _height 17 | if isinstance(img, bytes): 18 | __show__.draw(img, _width, _height) 19 | except ModuleNotFoundError as e: 20 | # v83x remove _maix_display and dts get lcd size 21 | import os 22 | os.system("cat /sys/firmware/devicetree/base/soc@03000000/board/lcd > /tmp/lcd") 23 | with open("/tmp/lcd", "r") as f: 24 | lcd = f.read().strip() 25 | if lcd.find("240,320") != -1: 26 | config(size=(240, 320)) 27 | except Exception as e: 28 | pass 29 | 30 | __display__ = None 31 | 32 | def as_image(): 33 | from maix import image 34 | global __display__ 35 | if __display__ is None: 36 | global _width, _height, __mode__ 37 | __display__ = image.new(mode=__mode__, size=(_width, _height)) 38 | return __display__ 39 | 40 | def width(): 41 | global _width 42 | return _width 43 | 44 | def height(): 45 | global _height 46 | return _height 47 | 48 | def show(img=None, box=(0, 0), local_show=True, remote_show=True): 49 | global __display__, __mode__, _width, _height 50 | if img is None: 51 | img = as_image() 52 | else: 53 | as_image() 54 | 55 | if remote_show: 56 | from maix import mjpg 57 | mjpg.store_mjpg(img) 58 | 59 | if local_show: 60 | try: 61 | from maix import image 62 | if isinstance(img, image.Image): 63 | if img.width != _width or img.height != _height: 64 | img = img.resize(_width, _height) 65 | img = img.tobytes() 66 | except ImportError as e: 67 | pass 68 | if __show__: 69 | __draw__(img) 70 | -------------------------------------------------------------------------------- /maix/i2c.py: -------------------------------------------------------------------------------- 1 | 2 | # ext_modules/libi2c/README.md 3 | 4 | ''' 5 | from maix import i2c 6 | print(i2c.scan()) 7 | dev = i2c.I2C('/dev/i2c-2', 0x26) 8 | print(dev) 9 | print(dev.read(0x1, 1)) 10 | 11 | >>> from maix import i2c 12 | >>> print(i2c.scan()) 13 | [38, 44, 118] 14 | >>> dev = i2c.I2C('/dev/i2c-2', 0x26) 15 | >>> print(dev) 16 | Device address: 0x26, tenbit: False, internal(word) address: 1 bytes, page max 8 bytes, delay: 1ms 17 | >>> print(dev.read(0x1, 1)) 18 | bytearray(b'\x13') 19 | >>> 20 | ''' 21 | 22 | try: 23 | from pylibi2c import I2CDevice as I2C, I2C_M_IGNORE_NAK, I2C_M_NOSTART, I2C_M_NO_RD_ACK 24 | def scan(path='/dev/i2c-2'): 25 | addrs = [] 26 | for addr in range(0x00, 0x7F): 27 | try: 28 | tmp = None 29 | tmp = I2C(path, addr) 30 | tmp.ioctl_read(0, 1) 31 | addrs.append(addr) 32 | except OSError as e: 33 | pass 34 | finally: 35 | if tmp: 36 | tmp.close() 37 | for addr in range(0x7F, 0xFF): 38 | try: 39 | tmp = None 40 | tmp = I2C(path, addr, tenbit=True) 41 | tmp.ioctl_read(0, 1) 42 | addrs.append(addr) 43 | except OSError as e: 44 | pass 45 | finally: 46 | if tmp: 47 | tmp.close() 48 | return addrs 49 | except ModuleNotFoundError as e: 50 | pass 51 | 52 | if __name__ == '__main__': 53 | print(scan()) 54 | bus, addr = '/dev/i2c-2', 0x26 55 | tmp = I2C(bus, addr) 56 | tmp.close() 57 | # i2c = I2CDevice(bus, addr, tenbit=False, iaddr_bytes=1, page_bytes=8, delay=1, flags=0) 58 | # iaddr_bytes(defualt 1 byte internal address) I2C device internal(word) address bytes, such as: 24C04 1 byte, 24C64 2 bytes 59 | # page_bytes(default 8 bytes per page) I2C max number of bytes per page, 1K/2K 8, 4K/8K/16K 16, 32K/64K 32 etc 60 | # flags(defualt 0) I2C i2c_ioctl_read/write flags, I2C_M_IGNORE_NAK, I2C_M_NOSTART, I2C_M_NO_RD_ACK 61 | # delay(defualt 1ms) I2C internal operate delay, unit millisecond 62 | # tenbit(defult False, 7-bit) I2C is 10 bit device address 63 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_image_get_histogram.py: -------------------------------------------------------------------------------- 1 | 2 | from maix import image 3 | 4 | # img = image.new(size=(10, 10), color=(255, 255, 255), mode="RGB") 5 | img = image.Image().open("ext_modules/_maix_image/example/test_image.jpg") 6 | tmp = img.get_histogram(bins=8, roi=(20, 20, 80, 80)) 7 | 8 | print("l_bins", len(tmp[0]), tmp[0]) 9 | print("a_bins", len(tmp[1]), tmp[2]) 10 | print("b_bins", len(tmp[2]), tmp[2]) 11 | 12 | print("get_threshold", tmp.get_threshold()) 13 | 14 | print("get_statistics", tmp.get_statistics()) 15 | 16 | print("get_percentile", tmp.get_percentile()) 17 | 18 | tmp = img.get_statistics() 19 | 20 | print(tmp) 21 | 22 | print("l Mean Median Mode STDev Min Max LQ UQ", tmp[0:8]) 23 | print("a Mean Median Mode STDev Min Max LQ UQ", tmp[8:16]) 24 | print("b Mean Median Mode STDev Min Max LQ UQ", tmp[16:24]) 25 | 26 | # openmv 27 | # "l_mean":42, "l_median":38, "l_mode":3, "l_stdev":27, "l_min":0, "l_max":100, "l_lq":19, "l_uq":65, 28 | # "a_mean":3, "a_median":1, "a_mode":0, "a_stdev":22, "a_min":-59, "a_max":81, "a_lq":-7, "a_uq":18, 29 | # "b_mean":5, "b_median":2, "b_mode":2, "b_stdev":27, "b_min":-88, "b_max":76, "b_lq":-12, "b_uq":25 30 | 31 | # maixpy3 32 | # 42, 37, 3, 27, 0, 98, 18, 66, 33 | # 2, -1, -1, 22, -72, 83, -8, 15, 34 | # 7, 1, -1, 26, -73, 76, -11, 25 35 | 36 | print(tmp[4:6], tmp[12:14], tmp[20:22]) ## default while 37 | 38 | # img.save("ts.jpg") 39 | 40 | ''' 41 | l_bins 8 [0.08312499523162842, 0.09140624850988388, 0.1795312464237213, 0.23015624284744263, 0.10546875, 0.1184374988079071, 0.19187499582767487, 0.0] 42 | a_bins 8 [0.0, 0.0, 0.08828125149011612, 0.24265624582767487, 0.559374988079071, 0.10968749970197678, 0.0, 0.0] 43 | b_bins 8 [0.0, 0.0, 0.08828125149011612, 0.24265624582767487, 0.559374988079071, 0.10968749970197678, 0.0, 0.0] 44 | get_threshold None 45 | get_statistics None 46 | get_percentile None 47 | 255 255 255 48 | [42, 37, 3, 27, 0, 98, 18, 66, 2, -1, -1, 22, -72, 83, -8, 15, 7, 1, -1, 26, -73, 76, -11, 25] 49 | l Mean Median Mode STDev Min Max LQ UQ [42, 37, 3, 27, 0, 98, 18, 66] 50 | a Mean Median Mode STDev Min Max LQ UQ [2, -1, -1, 22, -72, 83, -8, 15] 51 | b Mean Median Mode STDev Min Max LQ UQ [7, 1, -1, 26, -73, 76, -11, 25] 52 | [0, 98] [-72, 83] [-73, 76] 53 | ''' 54 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/person.py: -------------------------------------------------------------------------------- 1 | from lzma import MODE_NORMAL 2 | from maix import nn, display, camera , image 3 | import time 4 | from maix.nn import decoder 5 | import numpy as np 6 | 7 | def cal_fps(start , end): 8 | one_second = 1 9 | one_flash = end - start 10 | fps = one_second / one_flash 11 | return fps 12 | 13 | def draw_rectangle_with_title(img, box, disp_str , fps ): 14 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3],color=(255, 0, 0), thickness=1) 15 | img.draw_string(box[0], box[1]+ box[3] ,disp_str, scale=0.5,color=(0, 0, 255), thickness=1) 16 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=2 ,color=(0, 0, 255), thickness=2) 17 | 18 | 19 | model = { 20 | "bin": "/root/models/aipu_yolo_person.bin", 21 | # "param":"/root/models/VOC2012_awnn.param" 22 | } 23 | 24 | options = { 25 | "model_type": "aipu", 26 | "inputs": { 27 | "input0": (224, 224, 3) 28 | }, 29 | "outputs": { 30 | "output0": (7, 7, (1+4+1)*5) 31 | }, 32 | "mean": [127.5, 127.5, 127.5], 33 | "norm": [0.01448183, 0.01463443, 0.01391933], 34 | "scale":[0.32879806], 35 | } 36 | 37 | #加载模型 38 | print("load model") 39 | m = nn.load(model, opt=options) 40 | print("load ok") 41 | #获取处理图像大小 42 | w = options["inputs"]["input0"][1] 43 | h = options["inputs"]["input0"][0] 44 | 45 | # 设置标签和anchor大小 46 | labels = ["person"] 47 | anchors = [4.72, 6.26, 1.39, 3.53, 0.78, 1.9, 0.35, 0.95, 2.49, 4.87] 48 | 49 | # 声明解码器并初始化 50 | yolo2_decoder = decoder.Yolo2(len(labels), anchors, net_in_size=(w, h), net_out_size=(7, 7)) 51 | 52 | while 1: 53 | # 获取摄像头图像 54 | t = time.time() 55 | img = camera.capture().resize(size=(w, h)) 56 | 57 | #模型前向推理 58 | out = m.forward(img.tobytes(), quantize =1 ,layout = "chw") #返回对象是一个List对象,实际输出的内容是需要进行解包 59 | 60 | #解码器解码(后处理) 61 | boxes, probs = yolo2_decoder.run(out, nms=0.2, threshold=0.5, img_size=(224,224)) 62 | 63 | #图像渲染 64 | for i, box in enumerate(boxes): 65 | class_id = probs[i][0] 66 | prob = probs[i][1][class_id] 67 | disp_str = "{}:{:.2f}%".format(labels[class_id], prob*100) 68 | fps = cal_fps(t, time.time()) 69 | draw_rectangle_with_title(img, box, disp_str, fps) 70 | 71 | #图像端侧显示 72 | display.show(img) 73 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/example/retinaface.py: -------------------------------------------------------------------------------- 1 | from http.client import ImproperConnectionState 2 | from pydoc import doc 3 | from statistics import variance 4 | from time import time 5 | 6 | class Retinaface(): 7 | mdsc_path = "/root/mud/v831_retinaface.mud" 8 | 9 | # v831 10 | variances = [0.1, 0.2] 11 | steps = [8, 16, 32] 12 | min_sizes = [16, 32, 64, 128, 256, 512] 13 | #R329 14 | # variances = [0.1, 0.2] 15 | # steps = [8, 16, 32, 64] 16 | # min_sizes = [10, 16, 24, 32, 48, 64, 96, 128, 192, 256] 17 | 18 | def __init__(self) -> None: 19 | from maix import nn 20 | self.model = nn.load(self.mdsc_path,opt = None) 21 | from maix.nn import decoder 22 | self.decoder = decoder.Retinaface([224,224] , self.steps , self.min_sizes, self.variances) 23 | 24 | def __del__(self): 25 | del self.model 26 | del self.decoder 27 | 28 | def cal_fps(self ,start , end): 29 | one_second = 1 30 | one_flash = end - start 31 | fps = one_second / one_flash 32 | return fps 33 | 34 | def draw_fps(self,img , fps): 35 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=1,color=(255, 0, 255), thickness=1) 36 | 37 | 38 | def draw_rectangle(self,img, box): 39 | img.draw_rectangle(box[0], box[1], box[2], box[3],color=(230 ,230, 250), thickness=2) 40 | 41 | def draw_point(self,img,landmark): 42 | for i in range(5): 43 | x = landmark[2 * i ] 44 | y = landmark[2 * i + 1] 45 | img.draw_rectangle(x-2,y-2, x+2,y+2,color= (193 ,255 ,193), thickness =-1) 46 | 47 | 48 | def process(self,input): 49 | out = self.model.forward(input, quantize=1, layout = "chw") # retinaface decoder only support chw layout 50 | boxes , landmarks = self.decoder.run(out, nms = 0.2 ,score_thresh = 0.7 , outputs_shape =[[1,4,2058],[1,2,2058],[1,10,2058]]) 51 | for i,box in enumerate(boxes): 52 | self.draw_rectangle(input,box) 53 | self.draw_point(input , landmarks[i]) 54 | 55 | def main(): 56 | from maix import display, camera 57 | app = Retinaface() 58 | 59 | while True: 60 | img = camera.capture().resize(size=(224,224)) 61 | app.process(img) 62 | display.show(img) 63 | # break 64 | main() -------------------------------------------------------------------------------- /ext_modules/libi2c/src/i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIB_I2C_H_ 2 | #define _LIB_I2C_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | /* I2c device */ 13 | typedef struct i2c_device { 14 | int bus; /* I2C Bus fd, return from i2c_open */ 15 | unsigned short addr; /* I2C device(slave) address */ 16 | unsigned char tenbit; /* I2C is 10 bit device address */ 17 | unsigned char delay; /* I2C internal operation delay, unit millisecond */ 18 | unsigned short flags; /* I2C i2c_ioctl_read/write flags */ 19 | unsigned int page_bytes; /* I2C max number of bytes per page, 1K/2K 8, 4K/8K/16K 16, 32K/64K 32 etc */ 20 | unsigned int iaddr_bytes; /* I2C device internal(word) address bytes, such as: 24C04 1 byte, 24C64 2 bytes */ 21 | } I2CDevice; 22 | 23 | /* Close i2c bus */ 24 | void i2c_close(int bus); 25 | 26 | /* Open i2c bus, return i2c bus fd */ 27 | int i2c_open(const char *bus_name); 28 | 29 | /* Initialize I2CDevice with default value */ 30 | void i2c_init_device(I2CDevice *device); 31 | 32 | /* Get i2c device description */ 33 | char *i2c_get_device_desc(const I2CDevice *device, char *buf, size_t size); 34 | 35 | /* Select i2c device on i2c bus */ 36 | int i2c_select(int bus, unsigned long dev_addr, unsigned long tenbit); 37 | 38 | /* I2C internal(word) address convert */ 39 | void i2c_iaddr_convert(unsigned int int_addr, unsigned int iaddr_bytes, unsigned char *addr); 40 | 41 | /* I2C file I/O read, write */ 42 | ssize_t i2c_read(const I2CDevice *device, unsigned int iaddr, void *buf, size_t len); 43 | ssize_t i2c_write(const I2CDevice *device, unsigned int iaddr, const void *buf, size_t len); 44 | 45 | /* I2c ioctl read, write can set i2c flags */ 46 | ssize_t i2c_ioctl_read(const I2CDevice *device, unsigned int iaddr, void *buf, size_t len); 47 | ssize_t i2c_ioctl_write(const I2CDevice *device, unsigned int iaddr, const void *buf, size_t len); 48 | 49 | /* I2C read / write handle function */ 50 | typedef ssize_t (*I2C_READ_HANDLE)(const I2CDevice *dev, unsigned int iaddr, void *buf, size_t len); 51 | typedef ssize_t (*I2C_WRITE_HANDLE)(const I2CDevice *dev, unsigned int iaddr, const void *buf, size_t len); 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /tests/maix_v831/play_camera_mp4.py: -------------------------------------------------------------------------------- 1 | from maix import display, camera 2 | import pyaudio 3 | import av 4 | import threading 5 | import time 6 | 7 | class funation: 8 | status = 0 9 | def __init__(self,device=None): 10 | self.event = self.run 11 | display.show(camera.capture()) 12 | self.tim = time.time() 13 | self.device = device 14 | def __del__(self): 15 | print("paly exit") 16 | def play(self): 17 | try: 18 | # recommend flv 19 | # ffmpeg -r 30 -i bad_apple.mp4 -s 240x240 output.mp4 20 | # adb push ./output.mp4 /mnt/UDISK/ 21 | # adb push ./test.py / && adb shell 'python ./test.py' 22 | path_to_video = '/root/bad_apple.mp4' 23 | container = av.open(path_to_video) 24 | ai_stream = container.streams.audio[0] 25 | vi_stream = container.streams.video[0] 26 | fifo = av.AudioFifo() 27 | p = pyaudio.PyAudio() 28 | ao = p.open(format=pyaudio.paFloat32, channels=2, rate=22050, output=True) 29 | for frame in container.decode(video=0, audio=0): 30 | if 'Audio' in repr(frame): 31 | frame.pts = None 32 | fifo.write(frame) 33 | for frame in fifo.read_many(4096): 34 | ao.write(frame.planes[0].to_bytes()) 35 | if 'Video' in repr(frame): 36 | display.show(bytes(frame.to_rgb().planes[0])) 37 | if self.device.funaction_status == -1: 38 | ao.stop_stream() 39 | ao.close() 40 | p.terminate() 41 | return 42 | except Exception as e: 43 | print(e) 44 | finally: 45 | ao.stop_stream() 46 | ao.close() 47 | p.terminate() 48 | def run(self): 49 | if self.status == 0: 50 | threading.Thread(target=self.play).start() 51 | self.status = 1 52 | time.sleep(0.1) 53 | 54 | 55 | if __name__ == "__main__": 56 | import signal 57 | def handle_signal_z(signum,frame): 58 | print("APP OVER") 59 | exit(0) 60 | signal.signal(signal.SIGINT,handle_signal_z) 61 | start = funation() 62 | while True: 63 | start.event() 64 | -------------------------------------------------------------------------------- /docs/pwm.md: -------------------------------------------------------------------------------- 1 | ## pwm.py 2 | 3 | see this https://github.com/scottellis/pwmpy 4 | 5 | A simple Python class to work with the Linux PWM kernel driver. 6 | 7 | Written for the Raspberry Pi and the hardware pwm timers, but should work with other SOCs. 8 | 9 | Requires that a PWM kernel driver is loaded appropriately which on the RPi normally means a dts overlay. 10 | 11 | Instructions for building and loading an appropriate dts for the RPi can be found [here][rpi-hardware-pwm]. 12 | 13 | I'm using a custom [Yocto built O/S][rpi-yocto] where pwm overlays are installed by default. 14 | 15 | Here is a simple interactive example using the PWM class 16 | 17 | root@rpi3:~# python3 18 | Python 3.5.2 (default, Nov 22 2016, 06:54:46) 19 | [GCC 6.2.0] on linux 20 | Type "help", "copyright", "credits" or "license" for more information. 21 | 22 | Import the *PWM* class from `pwm.py` 23 | 24 | >>> from pwm import PWM 25 | 26 | Create an instance of the class for the *PWM0* timer 27 | 28 | >>> pwm0 = PWM(0) 29 | 30 | Call *export()* before first use 31 | 32 | >>> pwm0.export() 33 | 34 | Setup a 1 ms period, 25% duty cycle pulse (period and duty\_cycle units are nanoseconds) 35 | 36 | >>> pwm0.period = 1000000 37 | >>> pwm0.duty_cycle = 250000 38 | 39 | Start the pwm timer 40 | 41 | >>> pwm0.enable = True 42 | 43 | Change the duty cycle to 50% 44 | 45 | >>> pwm0.duty_cycle = 500000 46 | 47 | Turn off the timer 48 | 49 | >>> pwm0.enable = False 50 | 51 | Create an instance for the *PWM1* timer 52 | 53 | >>> pwm1 = PWM(1) 54 | >>> pwm1.export() 55 | 56 | Setup a servo-like pulse with a 50 ms period and 2 ms duty\_cycle 57 | 58 | >>> pwm1.period = 50000000 59 | >>> pwm1.duty_cycle = 2000000 60 | >>> pwm1.enable = True 61 | 62 | Set the servo pulse to 2.5 ms 63 | 64 | >>> pwm1.duty_cycle = 2500000 65 | 66 | Set the servo pulse to 1.5 ms 67 | 68 | >>> pwm1.duty_cycle = 1500000 69 | 70 | Back to 2.0 ms 71 | 72 | >>> pwm1.duty_cycle = 2000000 73 | 74 | Turn it off 75 | 76 | >>> pwm1.enable = False 77 | 78 | Unexport both timers 79 | 80 | >>> pwm0.unexport() 81 | >>> pwm1.unexport() 82 | >>> quit() 83 | 84 | 85 | [rpi-hardware-pwm]: http://www.jumpnowtek.com/rpi/Using-the-Raspberry-Pi-Hardware-PWM-timers.html 86 | [rpi-yocto]: http://www.jumpnowtek.com/rpi/Raspberry-Pi-Systems-with-Yocto.html 87 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/doc/Module_Development_Guide.md: -------------------------------------------------------------------------------- 1 | 2021年10月, dianjixz 所著. 2 | 3 | # 该指南可用于个人开发者开发自己想要的maix_version功能 4 | 5 | _maix_image模块采用c++语言进行开发,通过pybind11模块进行C++与python的函数绑定. 6 | 模块采用轻耦合设计,对于图像的不同功能采用不同的C++类对象进行封装.软件实现上为菱形继承方法,请不要破坏整个软件实现结构. 7 | class any_image类是整个_maix_image模块的基础图像容器,请尽量保持该类的不变.该类应由所有图像处理类`虚继承`. 8 | class maix_image类是对应的python接口类,主要给pybind11提供统一的类绑定函数,你实现的图像方法类应由该类进行继承. 9 | 10 | ~~~ bash 11 | any_image 12 | | | 13 | V V 14 | maix_vision other 15 | | | 16 | T 17 | V 18 | maix_image 19 | ~~~ 20 | 21 | ~~~ C++ 22 | class any_image 23 | { 24 | private: 25 | public: 26 | Any py_to_pram[4][4]; // 快速转换表 27 | libmaix_image_t *_img; //图像指针 28 | int _maix_image_width; //图像宽度 29 | int _maix_image_height; //图像高度 30 | std::string _maix_image_type; //图像类型 31 | int _maix_image_size; //图像大小 32 | any_image(); //构造函数 33 | py_input_image_mode_t get_img_type(py::object &input_img); //python对象识别函数 34 | int get_to(std::string &mode); //返回快速转换表第一维索引 35 | }; 36 | 37 | ~~~ 38 | 当 class other类虚拟继承any_image类后,在other类内部可以使用this指针访问any_image类内容.请开发者注意内存安全性. 39 | 当编写完自己的other类后可以在maix_image类中进行public继承,然后在py_maix_image.cpp文件中进行函数绑定,之后就可以在pyhton的image类对象中使用作者自己的方法了. 40 | 41 | 相关编程请参考maix_vision的实现. 42 | 欢迎个人开发者参与_maix_image模块的开发,为开源社区贡献自己的力量. 43 | 44 | 45 | 46 | 47 | 48 | 个人参与开发模块实例过程:(在ubuntu中的过程,windows开发者可以在wls中完成以下操作) 49 | 50 | 第一步,从github上拉取maixpy3的源代码 51 | ~~~ bash 52 | git clone https://github.com/sipeed/MaixPy3.git 53 | cd MaixPy3 54 | git submodule update --init 55 | ~~~ 56 | 第二步,安装交叉编译工具链 57 | ~~~ bash 58 | sudo apt install libffi-dev 59 | 60 | wget https://github.com/sipeed/libmaix/releases/download/v0.1.0/toolchain-sunxi-musl-pack-2021-01-09.tar.xz 61 | 62 | sudo cp toolchain-sunxi-musl-pack-2021-01-09.tar.xz /opt 63 | sudo xz -d toolchain-sunxi-musl-pack-2021-01-09.tar.xz 64 | sudo tar xvf toolchain-sunxi-musl-pack-2021-01-09.tar 65 | sudo mv toolchain-sunxi-musl-pack-2021-01-09 v83x 66 | source /opt/v83x/envsetup.sh 67 | ~~~ 68 | 第三步编译maixpy3 69 | ~~~ bash 70 | python3.8 setup.py bdist_wheel maix_v83x 71 | #如果出现libffi.so.6错误,请查看本机的libffi库,如果版本过高可以通过建立软链接的方式创建出libffi.so.6 72 | #如果出现pybind11没有,可运行python3.8 -m pip install pybind11进行安装. 73 | #注意在安装pybind11时可能会报没有权限,这个时候执行`sudo su`,进入root用户,然后执行`source /opt/v83x/envsetup.sh` 74 | #命令,加载交叉编译环境,然后再执行python3.8 -m pip install pybind11就可以装上了 75 | ~~~ 76 | 请开发者享受编写代码的乐趣. -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/yolo2_image.py: -------------------------------------------------------------------------------- 1 | from maix import nn 2 | from PIL import Image, ImageDraw, ImageFont 3 | from maix import display 4 | import time 5 | from maix.nn import decoder 6 | 7 | def draw_rectangle_with_title(img, box, disp_str, bg_color=(255, 0, 0), font_color=(255, 255, 255)): 8 | draw = ImageDraw.Draw(img) 9 | font = ImageFont.load_default() 10 | 11 | font_w, font_h = font.getsize(disp_str) 12 | draw.rectangle((box[0], box[1], box[0] + box[2], box[1] + box[3]), fill=None, outline=bg_color, width=2) 13 | draw.rectangle((box[0], box[1] - font_h, box[0] + font_w, box[1]), fill=bg_color) 14 | draw.text((box[0], box[1] - font_h), disp_str, fill=font_color, font=font) 15 | 16 | 17 | 18 | test_jpg = "/root/face.jpg" 19 | model = { 20 | "param": "/root/models/yolo2_face_awnn.param", 21 | "bin": "/root/models/yolo2_face_awnn.bin" 22 | } 23 | 24 | options = { 25 | "model_type": "awnn", 26 | "inputs": { 27 | "input0": (224, 224, 3) 28 | }, 29 | "outputs": { 30 | "output0": (7, 7, (1+4+1)*5) 31 | }, 32 | "mean": [127.5, 127.5, 127.5], 33 | "norm": [0.0078125, 0.0078125, 0.0078125], 34 | } 35 | print("-- load model:", model) 36 | m = nn.load(model, opt=options) 37 | print("-- load ok") 38 | 39 | print("-- read image") 40 | img = Image.open(test_jpg) 41 | w = options["inputs"]["input0"][1] 42 | h = options["inputs"]["input0"][0] 43 | img = img.resize((w, h)) 44 | # # img.show() 45 | print("-- read image ok") 46 | 47 | 48 | labels = ["person"] 49 | anchors = [1.19, 1.98, 2.79, 4.59, 4.53, 8.92, 8.06, 5.29, 10.32, 10.65] 50 | yolo2_decoder = decoder.Yolo2(len(labels), anchors, net_in_size=(w, h), net_out_size=(7, 7)) 51 | 52 | loop_count = 50 53 | while loop_count > 0: 54 | t = time.time() 55 | out = m.forward(img, quantize=True, layout="hwc") 56 | print("-- forward: ", time.time() - t ) 57 | 58 | t = time.time() 59 | boxes, probs = yolo2_decoder.run(out, nms=0.3, threshold=0.5, img_size=(w, h)) 60 | print("-- decode: ", time.time() - t ) 61 | 62 | t = time.time() 63 | for i, box in enumerate(boxes): 64 | class_id = probs[i][0] 65 | prob = probs[i][1][class_id] 66 | disp_str = "{}:{:.2f}%".format(labels[class_id], prob*100) 67 | draw_rectangle_with_title(img, box, disp_str) 68 | print("-- draw: ", time.time() - t ) 69 | 70 | t = time.time() 71 | display.show(img) 72 | print("-- show: ", time.time() - t ) 73 | 74 | loop_count -= 1 75 | 76 | 77 | -------------------------------------------------------------------------------- /ext_modules/libi2c/example/pylibi2c_tools.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import argparse 3 | import pylibi2c 4 | 5 | 6 | if __name__ == '__main__': 7 | parser = argparse.ArgumentParser() 8 | 9 | # Required args 10 | parser.add_argument('-b', '--bus', help='i2c bus, such as /dev/i2c-1', type=str, required=True) 11 | parser.add_argument('-d', '--device', help='i2c device address, such as 0x56', type=str, required=True) 12 | 13 | # Device option args 14 | parser.add_argument('--iaddr', help='i2c internal address', type=str, default="0x0") 15 | parser.add_argument('--delay', help='i2c r/w delay, unit is msec', type=int, default=1) 16 | parser.add_argument('--iaddr_bytes', help='i2c internal address bytes', type=int, default=1) 17 | parser.add_argument('--page_bytes', help='i2c per page max number of bytes', type=int, default=8) 18 | 19 | # Read/write options 20 | parser.add_argument('--data', help='write data', type=str) 21 | parser.add_argument('--size', help='read data size', type=int) 22 | parser.add_argument('--ioctl', help='using ioctl r/w i2c', type=bool, default=False) 23 | args = vars(parser.parse_args()) 24 | 25 | try: 26 | 27 | bus = args.get('bus') 28 | device = int(args.get('device'), 16) 29 | 30 | delay = args.get('delay') 31 | iaddr = int(args.get('iaddr'), 16) 32 | page_bytes = args.get('page_bytes') 33 | iaddr_bytes = args.get('iaddr_bytes') 34 | 35 | data = args.get('data') 36 | size = args.get('size') 37 | ioctl = args.get('ioctl') 38 | 39 | if data is None and size is None: 40 | raise RuntimeError("'data' or 'size' must specified one, 'data' for write, 'size' for read") 41 | 42 | # Create a i2c device 43 | i2c = pylibi2c.I2CDevice(bus=bus, addr=device, page_bytes=page_bytes, iaddr_bytes=iaddr_bytes, delay=delay) 44 | 45 | if data: 46 | write_handle = i2c.ioctl_write if ioctl else i2c.write 47 | ret = write_handle(iaddr, bytes(data.encode("ascii"))) 48 | print("Write: '{0:s}' to address: 0x{1:x}".format(data, iaddr)) 49 | print("Result:{}".format(ret)) 50 | else: 51 | read_handle = i2c.ioctl_read if ioctl else i2c.read 52 | data = read_handle(iaddr, size) 53 | print("Read: {0:d} bytes data from address: 0x{1:x}".format(size, iaddr)) 54 | print("Result:'{}'".format(data.decode("ascii"))) 55 | except (TypeError, IOError, ValueError, RuntimeError) as err: 56 | print("I2C R/W error:{}".format(err)) 57 | 58 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/r329_yolo2_person.py: -------------------------------------------------------------------------------- 1 | class Yolo: 2 | path = { 3 | #R329 4 | "bin": "/root/models/aipu_yolo_person.bin" 5 | 6 | # V831 7 | # "bin": "./models/awnn_yolo_person.bin" 8 | # "param": "./models/awnn_yolo_person.param" 9 | } 10 | 11 | input_size = (224, 224, 3) 12 | output_size =(7, 7, (1+4+1)*5) 13 | options = { 14 | "model_type": "aipu", 15 | "inputs": { 16 | "input0": input_size 17 | }, 18 | "outputs": { 19 | "output0": output_size 20 | }, 21 | "mean": [127.5, 127.5, 127.5], 22 | "norm": [0.0078125, 0.0078125, 0.0078125], 23 | "scale":[10.872787],# R329 有此选项,V831没有这个选项 24 | } 25 | 26 | labels = ["person"] 27 | anchors = [4.72, 6.26, 1.39, 3.53, 0.78, 1.9, 0.35, 0.95, 2.49, 4.87] 28 | 29 | def __init__(self) -> None: 30 | from maix import nn 31 | print(" - - load model :",self.path) 32 | self.model = nn.load(self.path , opt = self.options) 33 | print("- -load ok") 34 | from maix.nn import decoder 35 | print("- - load decoder") 36 | self.decoder = decoder.Yolo2(len(self.labels) , self.anchors , net_in_size = (self.input_size[1], self.input_size[0]) ,net_out_size = (self.output_size[1],self.output_size[0])) 37 | print("-- decoder load done") 38 | 39 | def __del__(self): 40 | del self.model 41 | del self.decoder 42 | 43 | def cal_fps(self ,start , end): 44 | one_second = 1 45 | one_flash = end - start 46 | fps = one_second / one_flash 47 | return fps 48 | 49 | def draw_rectangle_with_title(self ,img, box, disp_str , fps ): 50 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3],color=(255, 0, 0), thickness=1) 51 | img.draw_string(box[0], box[1]+ box[3] ,disp_str, scale=0.5,color=(0, 0, 255), thickness=1) 52 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=2 ,color=(0, 0, 255), thickness=2) 53 | 54 | # maix 55 | from maix import display,camera 56 | import time 57 | global m 58 | m = Yolo() 59 | 60 | while True: 61 | img = camera.capture().resize(size=(m.input_size[0] ,m.input_size[1])) 62 | t = time.time() 63 | out = m.model.forward(img.tobytes(), quantize=1, layout = "hwc") 64 | boxes, probs = m.decoder.run(out, nms=0.5, threshold=0.5, img_size=(224,224)) 65 | for i, box in enumerate(boxes): 66 | class_id = probs[i][0] 67 | prob = probs[i][1][class_id] 68 | disp_str = "{}:{:.2f}%".format(m.labels[class_id], prob*100) 69 | fps = m.cal_fps(t, time.time()) 70 | m.draw_rectangle_with_title(img, box, disp_str, fps) 71 | display.show(img) -------------------------------------------------------------------------------- /docs/develop.md: -------------------------------------------------------------------------------- 1 | # develop readme 2 | 3 | ## Py module usage 4 | 5 | see setup.py 6 | 7 | - python setup.py build 8 | 9 | - pip install . 10 | 11 | - pip uninstall MaixPy3 -y 12 | 13 | > *sudo python setup.py install* 14 | 15 | - python3.8 setup.py bdist_wheel 16 | 17 | - python3.8 setup.py bdist_egg 18 | 19 | - python3.8 setup.py bdist 20 | 21 | - pip install MaixPy3*whl -y --upgrade 22 | 23 | add xxxx/__init__.py 24 | 25 | ## Py Call C module 26 | 27 | such as libjpeg 28 | 29 | - sudo apt-get install libjpeg-dev 30 | 31 | such as libopencv-*-dev 32 | 33 | - sudo apt-get install libopencv-*-dev 34 | 35 | see ext_modules/_maix 36 | 37 | ## C module usage 38 | 39 | see Makefile 40 | 41 | - cd ext_modules/libi2c 42 | 43 | - make all 44 | 45 | - make clean 46 | 47 | add ext_modules/xxxx 48 | header file add MANIFEST.in. 49 | 50 | ## tox test usage 51 | 52 | see tox.ini 53 | 54 | - tox 55 | 56 | add tests/test_xxxx.py 57 | 58 | auto run test_xxxx.py 59 | 60 | ## py call usage 61 | 62 | - pip install --upgrade xxxx 63 | 64 | - python -c "import maix" 65 | 66 | ## clean cmd 67 | 68 | - find . -name '__pycache__' -type d -exec rm -rf {} \; 69 | 70 | - python3 setup.py clean --all 71 | 72 | ## build cmd 73 | 74 | your x86 75 | 76 | - python3 setup.py bdist_wheel 77 | 78 | your v83x 79 | 80 | - source /opt/v83x_linux_x86_python3.8_toolchain/envsetup.sh 81 | 82 | - python3.8 setup.py bdist_wheel maix_v83x 83 | 84 | - rm -rf dist/* && python3.8 setup.py clean --all bdist_wheel maix_v83x && adb shell 'rm /root/maixpy3-0.5.*-cp38-cp38-linux_armv7l.whl' && adb push ./dist/maixpy3-0.5.*-cp38-cp38-linux_armv7l.whl /root/ && adb shell "pip install /root/maixpy3-0.5.*-cp38-cp38-linux_armv7l.whl --upgrade" 85 | 86 | - adb shell 'rm /root/maixpy3-0.5.*-cp38-cp38-linux_armv7l.whl' && adb push ./dist/maixpy3-0.5.*-cp38-cp38-linux_armv7l.whl /root/ && adb shell "pip install /root/maixpy3-0.5.*-cp38-cp38-linux_armv7l.whl --upgrade" 87 | 88 | your r329 89 | 90 | - source /opt/r329_linux_x86_python3.9_toolchain/envsetup.sh 91 | 92 | - python3.9 setup.py bdist_wheel maix_r329 93 | 94 | - rm /root/maixpy3-0.5.*-cp38-cp38-linux_armv7l.whl 95 | 96 | - python3.9 setup.py clean --all bdist_wheel maix_r329 && scp ./dist/maixpy3-0.5.*-cp39*.whl root@192.168.0.247:~/ 97 | 98 | - pip uninstall maixpy3 -y && pip install ~/maixpy3-0.5.*-cp39*.whl 99 | 100 | > pypi upload manylinux2014_aarch64 101 | 102 | ## pypi upload 103 | 104 | - python3 setup.py sdist 105 | - python3 setup.py build && pip3 install . 106 | - python3.8 setup.py bdist_wheel maix_v83x 107 | 108 | > pip3 install twine 109 | 110 | - twine upload dist/* --verbose 111 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_version_find_blobs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # //================================================================== 3 | # maix_vision.find_blobs(thresholds, roi = (0,0,0,0), x_stride = 2, y_stride = 2, invert = 0, area_threshold = 10, pixels_threshold = 10, merge = 0, margin = 0, tilt = 0, co = 1) 4 | # 查找图像中所有色块,并返回一个包括每个色块的色块对象的列表。 5 | # thresholds 必须是元组列表. [(minL, minA, minB, maxL, maxA, maxB)] 6 | # roi 是感兴趣区域的矩形元组(x,y,w,h)。如果未指定,ROI即整个图像的图像矩形。 操作范围仅限于 roi 区域内的像素。 7 | # x_stride 是查找某色块时需要跳过的x像素的数量。找到色块后,直线填充算法将精确像素。 若已知色块较大,可增加 x_stride 来提高查找色块的速度。 8 | # y_stride 是查找某色块时需要跳过的y像素的数量。找到色块后,直线填充算法将精确像素。 若已知色块较大,可增加 y_stride 来提高查找色块的速度。 9 | # invert 反转阈值操作,像素在已知颜色范围之外进行匹配,而非在已知颜色范围内。 10 | # 若一个色块的边界框区域小于 area_threshold ,则会被过滤掉。 11 | # 若一个色块的像素数小于 pixel_threshold ,则会被过滤掉。 12 | # merge 若为True,则合并所有没有被过滤掉的色块,这些色块的边界矩形互相交错重叠。 13 | # margin 可在相交测试中用来增大或减小色块边界矩形的大小。例如:边缘为1、相互间边界矩形为1的色块将被合并。 14 | # tilt设置是否查找最小斜矩形框,为0则不查找. 15 | # co为返回的颜色空间模型.可选为,如果不是特殊需要,请保持默认 16 | # 0 rgb 17 | # 1 lab 18 | # 2 hsv 19 | # 3 灰度 20 | # 返回值:[{'x': 140, 'y': 88, 'w': 15, 'h': 7, 'pixels': 43, 'cx': 147, 'cy': 91}] 21 | # (x, y, w, h)色块的外框,pixels,色块的像素大小,(cx, cy)色块的中心点. 22 | # 时间:2021年9月16日 ,2021年11月16日更新 23 | # 作者:dianjixz 24 | # //================================================================== 25 | from maix import image, display, camera 26 | import time 27 | 28 | 29 | class funation: 30 | green = [(28, -36, -14, 68, -5, 15)] # 绿色 31 | red = [(20, 22, -3, 55, 52, 42)] # 红色 32 | yellow = [(35, -6, 22, 88, 5, 81)] # 黄色 33 | bull = [(13, 11, -91, 54, 48, -28)] # 蓝色 34 | white = [(41, 6, -32, 74, 11, -12)] # 白色 35 | black = [(10, -3, -28, 50, 10, -4)] # 黑色 36 | 37 | def __init__(self, device=None): 38 | self.event = self.run 39 | 40 | def __del__(self): 41 | print("maix_vision.find_blobs will exit!") 42 | 43 | def run(self): 44 | tmp = camera.capture() 45 | t = time.time() 46 | ma = tmp.find_blobs(self.bull) 47 | t = time.time() - t 48 | print("-- forward time: {}s".format(t)) 49 | # print(ma) 50 | if ma: 51 | for i in ma: 52 | tmp.draw_rectangle(i["x"], i["y"], i["x"] + i["w"], 53 | i["y"] + i["h"], color=(255, 0, 0), thickness=1) 54 | display.show(tmp) 55 | 56 | 57 | if __name__ == "__main__": 58 | import signal 59 | 60 | def handle_signalm(signum, frame): 61 | print("father over") 62 | exit(0) 63 | signal.signal(signal.SIGINT, handle_signalm) 64 | start = funation() 65 | while True: 66 | start.event() 67 | 68 | # tmp.draw_rectangle(10, 10, 20, 20, color=(255, 0, 0), thickness=1) 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # c/cpp 132 | *.o 133 | *.so 134 | *.obj 135 | objs 136 | depend 137 | *.a 138 | 139 | examples/rtsp_pyqt 140 | sipeed_v83x_opencv4.1 141 | .vscode/ 142 | ext_modules/_maix_opencv/example/test.py 143 | .vscode-ctags 144 | cpython 145 | start.sh 146 | _maix_opencvbak.cpp -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/r329_yolo2_camera.py: -------------------------------------------------------------------------------- 1 | class Yolo: 2 | path = { 3 | #R329 4 | "bin": "./models/aipu_yolo_voc.bin" 5 | 6 | # V831 7 | # "bin": "./models/awnn_yolo_voc.bin" 8 | # "param": "./models/awnn_yolo_voc.param" 9 | } 10 | 11 | input_size = (224, 224, 3) 12 | output_size =(7, 7, (1+4+20)*5) 13 | options = { 14 | "model_type": "aipu", 15 | "inputs": { 16 | "input0": input_size 17 | }, 18 | "outputs": { 19 | "output0": output_size 20 | }, 21 | "mean": [127.5, 127.5, 127.5], 22 | "norm": [0.0078125, 0.0078125, 0.0078125], 23 | "scale":[8.031941],# R329 有此选项,V831没有这个选项 24 | } 25 | 26 | labels = ["aeroplane","bicycle","bird","boat","bottle","bus","car","cat","chair","cow","diningtable","dog","horse","motorbike","person","pottedplant","sheep","sofa","train","tvmonitor"] 27 | anchors = [0.4165, 0.693 , 0.9765, 1.6065, 1.5855, 3.122 , 2.821 , 1.8515 , 3.612 , 3.7275] 28 | 29 | def __init__(self) -> None: 30 | from maix import nn 31 | print(" - - load model :",self.path) 32 | self.model = nn.load(self.path , opt = self.options) 33 | print("- -load ok") 34 | from maix.nn import decoder 35 | print("- - load decoder") 36 | self.decoder = decoder.Yolo2(len(self.labels) , self.anchors , net_in_size = (self.input_size[1], self.input_size[0]) ,net_out_size = (self.output_size[1],self.output_size[0])) 37 | print("-- decoder load done") 38 | 39 | def __del__(self): 40 | del self.model 41 | del self.decoder 42 | 43 | def cal_fps(self ,start , end): 44 | one_second = 1 45 | one_flash = end - start 46 | fps = one_second / one_flash 47 | return fps 48 | 49 | def draw_rectangle_with_title(self ,img, box, disp_str , fps ): 50 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3],color=(255, 0, 0), thickness=1) 51 | img.draw_string(box[0], box[1]+ box[3] ,disp_str, scale=0.5,color=(0, 0, 255), thickness=1) 52 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=2 ,color=(0, 0, 255), thickness=2) 53 | 54 | # maix 55 | from maix import display,camera 56 | import time 57 | global m 58 | m = Yolo() 59 | 60 | while True: 61 | img = camera.capture().resize(size=(m.input_size[0] ,m.input_size[1])) 62 | t = time.time() 63 | out = m.model.forward(img.tobytes(), quantize=1, layout = "hwc") 64 | boxes, probs = m.decoder.run(out, nms=0.5, threshold=0.5, img_size=(224,224)) 65 | for i, box in enumerate(boxes): 66 | class_id = probs[i][0] 67 | prob = probs[i][1][class_id] 68 | disp_str = "{}:{:.2f}%".format(m.labels[class_id], prob*100) 69 | fps = m.cal_fps(t, time.time()) 70 | m.draw_rectangle_with_title(img, box, disp_str, fps) 71 | display.show(img) 72 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/r329_yolo2_cards.py: -------------------------------------------------------------------------------- 1 | class Yolo: 2 | path = { 3 | #R329 4 | "bin": "./models/aipu_yolo_card.bin" 5 | 6 | # V831 7 | # "bin": "./models/awnn_yolo_card.bin" 8 | # "param": "./models/awnn_yolo_card.param" 9 | } 10 | 11 | input_size = (224, 224, 3) 12 | output_size =(7, 7, (1+4+35)*5) 13 | options = { 14 | "model_type": "aipu", 15 | "inputs": { 16 | "input0": input_size 17 | }, 18 | "outputs": { 19 | "output0": output_size 20 | }, 21 | "mean": [127.5, 127.5, 127.5], 22 | "norm": [0.0078125, 0.0078125, 0.0078125], 23 | "scale":[10.872787],# R329 有此选项,V831没有这个选项 24 | } 25 | 26 | labels = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "mouse", "microbit", "ruler", "cat", "peer", "ship", "apple", "car", "pan", "dog", "umbrella", "airplane", "clock", "grape", ] 27 | anchors = [2.44, 2.25, 5.03, 4.91, 3.5, 3.53, 4.16, 3.94, 2.97, 2.84] 28 | 29 | def __init__(self) -> None: 30 | from maix import nn 31 | print(" - - load model :",self.path) 32 | self.model = nn.load(self.path , opt = self.options) 33 | print("- -load ok") 34 | from maix.nn import decoder 35 | print("- - load decoder") 36 | self.decoder = decoder.Yolo2(len(self.labels) , self.anchors , net_in_size = (self.input_size[1], self.input_size[0]) ,net_out_size = (self.output_size[1],self.output_size[0])) 37 | print("-- decoder load done") 38 | 39 | def __del__(self): 40 | del self.model 41 | del self.decoder 42 | 43 | def cal_fps(self ,start , end): 44 | one_second = 1 45 | one_flash = end - start 46 | fps = one_second / one_flash 47 | return fps 48 | 49 | def draw_rectangle_with_title(self ,img, box, disp_str , fps ): 50 | img.draw_rectangle(box[0], box[1], box[0] + box[2], box[1] + box[3],color=(255, 0, 0), thickness=1) 51 | img.draw_string(box[0], box[1]+ box[3] ,disp_str, scale=0.5,color=(0, 0, 255), thickness=1) 52 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=2 ,color=(0, 0, 255), thickness=2) 53 | 54 | # maix 55 | from maix import display,camera 56 | import time 57 | global m 58 | m = Yolo() 59 | 60 | while True: 61 | img = camera.capture().resize(size=(m.input_size[0] ,m.input_size[1])) 62 | t = time.time() 63 | out = m.model.forward(img.tobytes(), quantize=1, layout = "hwc") 64 | boxes, probs = m.decoder.run(out, nms=0.5, threshold=0.5, img_size=(224,224)) 65 | for i, box in enumerate(boxes): 66 | class_id = probs[i][0] 67 | prob = probs[i][1][class_id] 68 | disp_str = "{}:{:.2f}%".format(m.labels[class_id], prob*100) 69 | fps = m.cal_fps(t, time.time()) 70 | m.draw_rectangle_with_title(img, box, disp_str, fps) 71 | display.show(img) -------------------------------------------------------------------------------- /ext_modules/_maix_nn/src/py_maix_nn_app.c: -------------------------------------------------------------------------------- 1 | 2 | #include "Python.h" 3 | #include "py_maix_nn.h" 4 | #include "py_maix_nn_classifier.h" 5 | #include "libmaix_nn_classifier.h" 6 | #include "libmaix_nn_face.h" 7 | #include 8 | #include 9 | 10 | 11 | PyDoc_STRVAR(app_classifier_load_doc, "load classifier features.\n"); 12 | static PyObject* app_classifier_load(PyObject *self, PyObject *args, PyObject *kw_args) 13 | { 14 | libmaix_err_t err = LIBMAIX_ERR_NONE; 15 | static char *kwlist[] = {"model", "path", NULL}; 16 | const char* path = NULL; 17 | PyObject* model = NULL; 18 | 19 | if (!PyArg_ParseTupleAndKeywords(args, kw_args, "Os:load", kwlist, 20 | &model, &path)) 21 | { 22 | return NULL; 23 | } 24 | if(!path) 25 | { 26 | PyErr_Format(PyExc_ValueError, "path error, should be str type"); 27 | return NULL; 28 | } 29 | if(!model) 30 | { 31 | PyErr_Format(PyExc_ValueError, "model error, should be maix.nn.Model type"); 32 | return NULL; 33 | } 34 | void* classifier_obj = NULL; 35 | int feature_len = 0; 36 | int input_w = 0, input_h = 0; 37 | int class_num = 0; 38 | int sample_num = 0; 39 | err = libmaix_classifier_load(&classifier_obj, path, ((ModelObject*)model)->nn, &feature_len, &input_w, &input_h, &class_num, &sample_num); 40 | if(err != LIBMAIX_ERR_NONE) 41 | { 42 | PyErr_Format(PyExc_Exception, "app classifier save fail, code: %d", err); 43 | return NULL; 44 | } 45 | 46 | /* new object */ 47 | PyObject* call_args = PyList_New(0); 48 | PyObject* call_keywords = PyDict_New(); 49 | PyObject* o_classifier_obj = PyMaix_NN_app_Classifier_Type.tp_new(&PyMaix_NN_app_Classifier_Type, call_args, call_keywords); 50 | Py_DECREF(call_args);Py_DECREF(call_keywords); 51 | if(!o_classifier_obj) 52 | { 53 | PyErr_NoMemory(); 54 | return NULL; 55 | } 56 | App_Classifier_Object* o = (App_Classifier_Object*)o_classifier_obj; 57 | o->nn_model = (ModelObject*)model; 58 | o->class_num = class_num; 59 | o->sample_num = sample_num; 60 | o->classifier_obj = classifier_obj; 61 | o->feature_len = feature_len; 62 | o->input_w = input_w; 63 | o->input_h = input_h; 64 | o->init = true; 65 | return o_classifier_obj; 66 | } 67 | 68 | 69 | 70 | static PyMethodDef _maix_nn_app_methods[] = { 71 | {"classifier_load", (PyCFunction)app_classifier_load, METH_VARARGS | METH_KEYWORDS, app_classifier_load_doc}, 72 | {NULL, NULL, 0, NULL} 73 | }; 74 | 75 | 76 | struct PyModuleDef maix_nn_app_module = { 77 | PyModuleDef_HEAD_INIT, 78 | "_app", /* Module name */ 79 | _maix_nn__app_doc, /* Module _maixMethods */ 80 | -1, /* size of per-interpreter state of the module, size of per-interpreter state of the module,*/ 81 | _maix_nn_app_methods, 82 | }; 83 | 84 | 85 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/src/py_maix_nn_app.c: -------------------------------------------------------------------------------- 1 | 2 | #include "Python.h" 3 | #include "py_maix_nn.h" 4 | #include "py_maix_nn_classifier.h" 5 | #include "libmaix_nn_classifier.h" 6 | #include "libmaix_nn_face.h" 7 | #include 8 | #include 9 | 10 | 11 | PyDoc_STRVAR(app_classifier_load_doc, "load classifier features.\n"); 12 | static PyObject* app_classifier_load(PyObject *self, PyObject *args, PyObject *kw_args) 13 | { 14 | libmaix_err_t err = LIBMAIX_ERR_NONE; 15 | static char *kwlist[] = {"model", "path", NULL}; 16 | const char* path = NULL; 17 | PyObject* model = NULL; 18 | 19 | if (!PyArg_ParseTupleAndKeywords(args, kw_args, "Os:load", kwlist, 20 | &model, &path)) 21 | { 22 | return NULL; 23 | } 24 | if(!path) 25 | { 26 | PyErr_Format(PyExc_ValueError, "path error, should be str type"); 27 | return NULL; 28 | } 29 | if(!model) 30 | { 31 | PyErr_Format(PyExc_ValueError, "model error, should be maix.nn.Model type"); 32 | return NULL; 33 | } 34 | void* classifier_obj = NULL; 35 | int feature_len = 0; 36 | int input_w = 0, input_h = 0; 37 | int class_num = 0; 38 | int sample_num = 0; 39 | err = libmaix_classifier_load(&classifier_obj, path, ((ModelObject*)model)->nn, &feature_len, &input_w, &input_h, &class_num, &sample_num); 40 | if(err != LIBMAIX_ERR_NONE) 41 | { 42 | PyErr_Format(PyExc_Exception, "app classifier save fail, code: %d", err); 43 | return NULL; 44 | } 45 | 46 | /* new object */ 47 | PyObject* call_args = PyList_New(0); 48 | PyObject* call_keywords = PyDict_New(); 49 | PyObject* o_classifier_obj = PyMaix_NN_app_Classifier_Type.tp_new(&PyMaix_NN_app_Classifier_Type, call_args, call_keywords); 50 | Py_DECREF(call_args);Py_DECREF(call_keywords); 51 | if(!o_classifier_obj) 52 | { 53 | PyErr_NoMemory(); 54 | return NULL; 55 | } 56 | App_Classifier_Object* o = (App_Classifier_Object*)o_classifier_obj; 57 | o->nn_model = (ModelObject*)model; 58 | o->class_num = class_num; 59 | o->sample_num = sample_num; 60 | o->classifier_obj = classifier_obj; 61 | o->feature_len = feature_len; 62 | o->input_w = input_w; 63 | o->input_h = input_h; 64 | o->init = true; 65 | return o_classifier_obj; 66 | } 67 | 68 | 69 | 70 | static PyMethodDef _maix_nn_app_methods[] = { 71 | {"classifier_load", (PyCFunction)app_classifier_load, METH_VARARGS | METH_KEYWORDS, app_classifier_load_doc}, 72 | {NULL, NULL, 0, NULL} 73 | }; 74 | 75 | 76 | struct PyModuleDef maix_nn_app_module = { 77 | PyModuleDef_HEAD_INIT, 78 | "_app", /* Module name */ 79 | _maix_nn__app_doc, /* Module _maixMethods */ 80 | -1, /* size of per-interpreter state of the module, size of per-interpreter state of the module,*/ 81 | _maix_nn_app_methods, 82 | }; 83 | 84 | 85 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/Retinaface.py: -------------------------------------------------------------------------------- 1 | 2 | class Retinaface: 3 | path = { 4 | #R329 5 | "bin": "./models/aipu_retinaface.bin" 6 | 7 | # V831 8 | # "bin": "./models/awnn_retinaface.bin" 9 | # "param": "./models/awnn_retinaface.param" 10 | } 11 | input_size = (320,320,3) 12 | output0_size = (1,4,5875) 13 | output1_size = (1,2,5875) 14 | output2_size = (1,10,5875) 15 | options = { 16 | "model_type": "aipu", 17 | 18 | "inputs": { 19 | "input0": (320, 320, 3) 20 | }, 21 | 22 | "outputs": { 23 | "output0":output0_size, # HWC order 24 | "output1":output1_size, 25 | "output2":output2_size 26 | }, 27 | 28 | "mean": [127, 127, 127], 29 | "norm": [1 , 1 ,1], 30 | "scale":[32.752407 , 29.865177 , 14.620169], 31 | "steps":[8, 16, 32, 64], 32 | "min_sizes":[10, 16, 24, 32, 48, 64, 96, 128, 192, 256], 33 | "variance":[0.1,0.2] 34 | } 35 | 36 | def __init__(self) -> None: 37 | from maix import nn 38 | print(" - - load model :",self.path) 39 | self.model = nn.load(self.path , opt = self.options) 40 | print("- -load ok") 41 | from maix.nn import decoder 42 | print("- - load decoder") 43 | steps = self.options["steps"] 44 | min_sizes = self.options["min_sizes"] 45 | variances = self.options["variance"] 46 | h = self.input_size[0] 47 | w = self.input_size[1] 48 | self.decoder = decoder.Retinaface([h,w] ,steps, min_sizes,variances) 49 | 50 | def __del__(self): 51 | del self.model 52 | del self.decoder 53 | 54 | def cal_fps(start , end): 55 | one_second = 1 56 | one_flash = end - start 57 | fps = one_second / one_flash 58 | return fps 59 | 60 | def draw_fps(img , fps): 61 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=1,color=(255, 0, 255), thickness=1) 62 | 63 | 64 | def draw_rectangle(img, box): 65 | img.draw_rectangle(box[0], box[1], box[2], box[3],color=(230 ,230, 250), thickness=2) 66 | 67 | def draw_point(img,landmark): 68 | for i in range(5): 69 | x = landmark[2 * i ] 70 | y = landmark[2 * i + 1] 71 | img.draw_rectangle(x-2,y-2, x+2,y+2,color= (193 ,255 ,193), thickness =-1) 72 | 73 | #main 74 | from maix import display, camera 75 | import numpy as np 76 | from maix import nn 77 | import time 78 | global m 79 | m = Retinaface() 80 | 81 | while True: 82 | img = camera.capture().resize(size=(m.input_size[0],m.input_size[1])) 83 | t = time.time() 84 | out = m.forward(img.tobytes(), quantize=1, layout = "chw") 85 | boxes , landmarks = m.decoder.run(out, nms = 0.2 ,score_thresh = 0.7 , outputs_shape =[[1,4,5875],[1,2,5875],[1,10,5875]]) 86 | for i,box in enumerate(boxes): 87 | m.draw_rectangle(img,box) 88 | m.draw_point(img , landmarks[i]) 89 | fps = m.cal_fps(t, time.time()) 90 | m.draw_fps(img , fps) 91 | display.show(img) -------------------------------------------------------------------------------- /maix/zbar.py: -------------------------------------------------------------------------------- 1 | # https://online-barcode-reader.inliteresearch.com/ 2 | # http://zbar.sourceforge.net/ 3 | # pip3 install zbarlight 4 | # Has been replaced by image. 5 | 6 | class LazyImport: 7 | def __init__(self, module_name): 8 | self.module_name = module_name 9 | self.module = None 10 | def __getattr__(self, name): 11 | if self.module is None: 12 | self.module = __import__(self.module_name) 13 | return getattr(self.module, name) 14 | 15 | zbarlight = LazyImport("zbarlight") 16 | 17 | def scan_codes(code_types, img): 18 | """ 19 | Get *code_type* codes from a maix_image. 20 | *code_type* can be any of zbar supported code type [#zbar_symbologies]_: 21 | - **EAN/UPC**: EAN-13 (`ean13`), UPC-A (`upca`), EAN-8 (`ean8`) and UPC-E (`upce`) 22 | - **Linear barcode**: Code 128 (`code128`), Code 93 (`code93`), Code 39 (`code39`), Interleaved 2 of 5 (`i25`), 23 | DataBar (`databar`) and DataBar Expanded (`databar-exp`) 24 | - **2D**: QR Code (`qrcode`) 25 | - **Undocumented**: `ean5`, `ean2`, `composite`, `isbn13`, `isbn10`, `codabar`, `pdf417` 26 | .. [#zbar_symbologies] http://zbar.sourceforge.net/iphone/userguide/symbologies.html 27 | Args: 28 | code_types (list(str)): Code type(s) to search (see ``zbarlight.Symbologies`` for supported values). 29 | image (maix_image): Image to scan 30 | returns: 31 | A list of *code_type* code values or None 32 | """ 33 | try: 34 | if isinstance(code_types, str): 35 | import warnings 36 | code_types = [code_types] 37 | warnings.warn( 38 | 'Using a str for code_types is deprecated, please use a list of str instead', 39 | DeprecationWarning, 40 | ) 41 | from zbarlight import _zbarlight 42 | # Translate symbologies 43 | symbologies = [ 44 | _zbarlight.Symbologies.get(code_type.upper()) 45 | for code_type in set(code_types) 46 | ] 47 | # Check that all symbologies are known 48 | if None in symbologies: 49 | bad_code_types = [code_type for code_type in code_types if code_type.upper() not in _zbarlight.Symbologies] 50 | class UnknownSymbologieError(Exception): 51 | pass 52 | raise UnknownSymbologieError('Unknown Symbologies: %s' % bad_code_types) 53 | # Convert the image to be used by c-extension 54 | from maix import image 55 | if not isinstance(img, image.Image): 56 | raise RuntimeError('Bad or unknown image type') 57 | return _zbarlight.zbar_code_scanner(symbologies, img.copy().convert('L').tobytes(), img.width, img.height) 58 | except ModuleNotFoundError as e: 59 | print(e) 60 | return None 61 | 62 | if __name__ == '__main__': 63 | from maix import camera, display, zbar 64 | while True: 65 | tmp = camera.capture() 66 | result = zbar.scan_codes(["qrcode", "code39"], tmp) 67 | print(str(result)) 68 | display.show(tmp.draw_string(10, 10, str(result), 2.0, (255, 0, 0))) 69 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/example/LPR.py: -------------------------------------------------------------------------------- 1 | 2 | from time import time 3 | 4 | 5 | 6 | class LPR: 7 | loc_model_path = './loc.mud' 8 | reg_model_path = './reg.mud' 9 | chars =[ "皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", 10 | "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘" , "粤", 11 | "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青" , "宁", 12 | "新", "警", "学", "A" , "B" , "C" , "D" , "E" , "F" , "G", 13 | "H" , "J" , "K" , "L" , "M" , "N" , "P" , "Q" , "R" , "S", 14 | "T" , "U" , "V" , "W", "X" , "Y" , "Z" , "0" , "1", "2", "3", 15 | "4", "5", "6", "7", "8", "9", "-"] 16 | 17 | variances = [0.1, 0.2] 18 | steps = [8, 16, 32] 19 | min_sizes = [12, 24, 48, 96, 192, 320] 20 | 21 | def __init__(self) -> None: 22 | from maix import nn 23 | self.loc_model = nn.load(self.loc_model_path , opt = None) 24 | self.reg_model = nn.load(self.reg_model_path , opt = None) 25 | 26 | from maix.nn import decoder 27 | self.loc_decoder = decoder.license_plate_location([224,224] , self.steps , self.min_sizes, self.variances) 28 | self.reg_decoder = decoder.CTC((1,68,18)) 29 | 30 | def __del__(self): 31 | del self.loc_model 32 | del self.loc_decoder 33 | 34 | def cal_fps(self ,start , end): 35 | one_second = 1 36 | one_flash = end - start 37 | fps = one_second / one_flash 38 | return fps 39 | 40 | def draw_fps(self,img , fps): 41 | img.draw_string(0, 0 ,'FPS :'+str(fps), scale=1,color=(255, 0, 255), thickness=1) 42 | 43 | def draw_string(self , img , x , y , string , color): 44 | img.draw_string( x , y , string ,color = color) 45 | 46 | def draw_paste(self , src ,dst): 47 | src.paste(dst , 0 , 0) 48 | 49 | def draw_rectangle(self,img, box): 50 | img.draw_rectangle(box[0], box[1], box[2], box[3],color=(230 ,230, 250), thickness=2) 51 | 52 | def draw_point(self,img,landmark): 53 | for i in range(4): 54 | x = landmark[2 * i ] 55 | y = landmark[2 * i + 1] 56 | img.draw_rectangle(x-2,y-2, x+2,y+2,color= (193 ,255 ,193), thickness =-1) 57 | 58 | def process(self,input): 59 | loc_out = self.loc_model.forward(input, quantize=1, layout = "chw") # retinaface decoder only support chw layout 60 | boxes , landmarks = self.loc_decoder.run(loc_out, nms = 0.2 ,score_thresh = 0.7 , outputs_shape =[[1,4,2058],[1,2,2058],[1,8,2058]]) 61 | 62 | for i,box in enumerate(boxes): 63 | 64 | landmark = landmarks[i][:6] 65 | reg_in = input.affine(landmark , 94 , 24) 66 | reg_out = self.reg_model.forward(reg_in , quantize=1, layout = "chw") 67 | 68 | LP_number = self.reg_decoder.run(reg_out) 69 | string_LP = '' 70 | for id in LP_number: 71 | string_LP += self.chars[id] 72 | 73 | self.draw_string(input , box[0], box[1] , string_LP ,color=(225,0,0)) 74 | self.draw_paste(input , reg_in) 75 | self.draw_rectangle(input,box) 76 | self.draw_point(input , landmarks[i]) 77 | 78 | def main(): 79 | from maix import display, camera , image 80 | image.load_freetype("/home/res/sans.ttf") 81 | app = LPR() 82 | 83 | while True: 84 | img = camera.capture().resize(size=(224,224)) 85 | app.process(img) 86 | display.show(img) 87 | # break 88 | main() -------------------------------------------------------------------------------- /ext_modules/_maix_nn/example/self_learn_classifier.py: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # self learning classifier 4 | # download model from https://maixhub.com/model/zoo/86 first 5 | # 6 | 7 | from maix import nn 8 | from PIL import Image, ImageDraw 9 | from maix import camera, display 10 | import time 11 | from maix.nn.app.classifier import Classifier, load 12 | from evdev import InputDevice 13 | from select import select 14 | 15 | def get_keys(device): 16 | ''' 17 | @return is_left_pressed, is_right_pressed 18 | ''' 19 | left = False 20 | right = False 21 | r,w,x = select([device], [], [], 0) 22 | if r: 23 | for event in device.read(): 24 | if event.value == 1 and event.code == 0x02: 25 | right = True 26 | elif event.value == 1 and event.code == 0x03: 27 | left = True 28 | return left, right 29 | 30 | 31 | class_num = 3 32 | sample_num = 15 33 | feature_len = 512 34 | input_w = 224 35 | input_h = 224 36 | 37 | model = "./resnet18_1000_awnn.mud" 38 | print("-- load model:", model) 39 | m = nn.load(model) 40 | print("-- load ok") 41 | 42 | # model = { 43 | # "param": "./resnet18_1000_awnn.param", 44 | # "bin": "./resnet18_1000_awnn.bin" 45 | # } 46 | 47 | # options = { 48 | # "model_type": "awnn", 49 | # "inputs": { 50 | # "input0": (input_w, input_h, 3) 51 | # }, 52 | # "outputs": { 53 | # "190": (1, 1, feature_len) 54 | # }, 55 | # "mean": [127.5, 127.5, 127.5], 56 | # "norm": [0.0176, 0.0176, 0.0176], 57 | # } 58 | # print("-- load model:", model) 59 | # m = nn.load(model, opt=options) 60 | # print("-- load ok") 61 | 62 | 63 | keys_device = InputDevice('/dev/input/event0') 64 | def key_pressed(): 65 | l, r = get_keys(keys_device) 66 | return l, r 67 | 68 | key_l = False 69 | key_r = False 70 | 71 | classifier = Classifier(m, class_num, sample_num, feature_len, input_w, input_h) 72 | 73 | curr_class = 0 74 | curr_sample = 0 75 | while 1: 76 | img = camera.capture().resize(size=(input_w, input_h)) 77 | if not img: 78 | time.sleep(0.02) 79 | continue 80 | l, r = key_pressed() 81 | key_l = l | key_l 82 | key_r = r | key_r 83 | if key_l: 84 | if curr_class < class_num: 85 | print("add class") 86 | classifier.add_class_img(img) 87 | curr_class += 1 88 | elif curr_sample < sample_num: 89 | print("add sample") 90 | classifier.add_sample_img(img) 91 | curr_sample += 1 92 | if curr_sample == sample_num: 93 | print("train ...") 94 | classifier.train() 95 | print("train end ...") 96 | print("test save") 97 | classifier.save("m.classifier") 98 | print("test load") 99 | classifier = load(m, "m.classifier") 100 | print("test load ok") 101 | key_l = False 102 | if curr_class < class_num: 103 | img.draw_string(0, 0, f"press to record class {curr_class}", color=(255, 0, 0)) 104 | elif curr_sample < sample_num: 105 | img.draw_string(0, 0, f"press to record sample {curr_sample}", color=(255, 0, 0)) 106 | else: 107 | idx, distance = classifier.predict(img) 108 | img.draw_string(0, 0, f"class {idx}, distance: {distance}", color=(255, 0, 0)) 109 | print("predict class: {}, distance: {}".format(idx, distance)) 110 | display.show(img) 111 | 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

5 | MaixPy3 Logo 6 |

7 | 8 | > **This repository is DEPRECATED !** 9 | > 10 | > But you can remain use this repo for Sipeed Maix-II-Dock(v831) board. 11 | > 12 | > **Now we recommend to use [Sipeed/MaixPy](https://github.com/sipeed/maixpy) and new hardware platform**, more info visit it. 13 | 14 | 15 | # MaixPy3 ![GitHub forks](https://img.shields.io/github/forks/sipeed/maixpy3.svg?style=social) ![GitHub stars](https://img.shields.io/github/stars/sipeed/maixpy3.svg?style=social) ![GitHub watchers](https://img.shields.io/github/watchers/sipeed/maixpy3.svg?style=social) 16 | 17 | [![MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) [![PyPI version](https://badge.fury.io/py/maixpy3.svg)](https://badge.fury.io/py/maixpy3) ![Python](https://img.shields.io/badge/Python-3.5↗-ff69b4.svg) ![issue](https://img.shields.io/github/issues/sipeed/maixpy3.svg) 18 | 19 | MaixPy3 is a Python3 toolkit based on [cpython](https://github.com/python/cpython), which simplifies the development of applications on Linux AI edge devices through Python programming. 20 | 21 | ### [See the wiki.sipeed.com for more information](https://wiki.sipeed.com/maixpy3) 22 | 23 | ## Support Jupyter Environment 24 | 25 | Install [rpyc_ikernel](https://github.com/sipeed/rpyc_ikernel) kernel in jupyter notebook & lab to get an IDE that can remotely call Python code, videos, and image streaming. 26 | 27 | ![index.png](https://github.com/sipeed/rpyc_ikernel/raw/master/tests/images/index.png) 28 | 29 | ## Installation 30 | 31 | - ready linux ubuntu20.04 desktop 32 | 33 | ```bash 34 | sudo apt update && sudo apt install libjpeg-dev gcc libopencv-dev -qq -y && wget http://mirrors.kernel.org/ubuntu/pool/main/libf/libffi/libffi6_3.2.1-8_amd64.deb && sudo apt install ./libffi6_3.2.1-8_amd64.deb -qq -y 35 | 36 | python3 -m pip install pybind11 maixpy3 37 | ``` 38 | 39 | - run this python code 40 | 41 | ```python3 42 | from maix import camera, display 43 | display.show(camera.capture().draw_string(0, 0, "hello world!")) 44 | ``` 45 | 46 | ![uasge.png](./docs/uasge.png) 47 | 48 | ## Develop 49 | 50 | Under `linux x86_64`, use `python3 setup.py build && python3 -m pip install .` to complete the linux package construction. 51 | If you need `.whl` pre-compiled package, please change `build` to `bdist_wheel`. 52 | For other platforms, take the version of `maix_v83x` as an example, match the Python3 + cross-compilation chain of the corresponding platform, and run `python3.8 setup.py build maix_v83x` to complete the construction of the target platform package. 53 | 54 | Welcome to provide configurations of different platforms to [MaixPy3/envs/](./envs/) to adapt to the MaixPy3 environment. 55 | 56 | | **Platform** | **Status** | **Config** | **Progress** | **Toolchain** | 57 | | -------------- | ---------- | ----------- | ------------ | ------------ | 58 | | linux_pc & RPi_2B | working | [linux_desktop](./envs/linux_desktop.py) | 70% | [develop.md](./docs/develop.md) & [maixpy3_build.yml](.github/workflows/maixpy3_build.yml) 59 | | maix_v83x | working | [maix_v83x](./envs/maix_v83x.py) | 99% | [v83x_linux_x86_python3.8_toolchain](https://github.com/sipeed/MaixPy3/releases/tag/20210613) 60 | | maix_r329 | working | [maix_r329](./envs/maix_r329.py) | 99% | [r329_linux_x86_python3.9_toolchain](https://github.com/sipeed/MaixPy3/releases/tag/20211101) 61 | 62 | ## License 63 | 64 | Copyright (c) Sipeed Corporation. All rights reserved. 65 | 66 | Licensed under the MIT license. 67 | -------------------------------------------------------------------------------- /ext_modules/_maix/_maix.c: -------------------------------------------------------------------------------- 1 | 2 | #include "_maix.h" 3 | 4 | #define _VERSION_ "0.1" 5 | #define _NAME_ "_maix" 6 | 7 | #include "jpeglib.h" 8 | #include "string.h" 9 | 10 | PyDoc_STRVAR(_maix_doc, "MaixPy Python3 library.\n"); 11 | 12 | static PyObject *_maix_help() { 13 | return PyUnicode_FromString(_maix_doc); 14 | } 15 | 16 | PyDoc_STRVAR(_maix_rgb2jpg_doc, "rgb2jpg()\n\nConvert image(rgb888) bytes data to jpeg image bytes.\n"); 17 | static PyObject *PyJpegCompress(char *inData, int width, int height, int channels, int color_space, int quality); 18 | static PyObject *_maix_rgb2jpg(PyObject *self, PyObject *args) 19 | { 20 | PyObject *bytes = NULL; 21 | PyObject *inRGB = NULL; 22 | 23 | int width = 1, height = 1; 24 | int channels = 3, color_space = JCS_RGB, quality = 75; 25 | 26 | if (!PyArg_ParseTuple(args, "Oii|iii", &inRGB, 27 | &width, &height, &channels, &color_space, &quality)) 28 | return NULL; 29 | 30 | char *rgb_data = PyBytes_AS_STRING(inRGB); 31 | 32 | bytes = PyJpegCompress(rgb_data, width, height, channels, color_space, quality); 33 | 34 | return bytes; 35 | } 36 | 37 | static PyMethodDef _maix_methods[] = { 38 | {"help", (PyCFunction)_maix_help, METH_NOARGS, _maix_doc}, 39 | {"rgb2jpg", (PyCFunction)_maix_rgb2jpg, METH_VARARGS, _maix_rgb2jpg_doc}, 40 | {NULL} 41 | }; 42 | 43 | void define_constants(PyObject *module) { 44 | PyModule_AddObject(module, "_VERSION_", Py_BuildValue("s", _VERSION_)); 45 | } 46 | 47 | static struct PyModuleDef _maixmodule = { 48 | PyModuleDef_HEAD_INIT, 49 | _NAME_, /* Module name */ 50 | _maix_doc, /* Module _maixMethods */ 51 | -1, /* size of per-interpreter state of the module, size of per-interpreter state of the module,*/ 52 | _maix_methods, 53 | }; 54 | 55 | PyMODINIT_FUNC PyInit__maix(void) 56 | { 57 | 58 | PyObject *module; 59 | 60 | module = PyModule_Create(&_maixmodule); 61 | PyObject *version = PyUnicode_FromString(_VERSION_); 62 | 63 | /* Constants */ 64 | define_constants(module); 65 | 66 | /* Set module version */ 67 | PyObject *dict = PyModule_GetDict(module); 68 | PyDict_SetItemString(dict, "__version__", version); 69 | Py_DECREF(version); 70 | 71 | return module; 72 | } 73 | 74 | static PyObject *PyJpegCompress(char *inData, int width, int height, int channels, int color_space, int quality) 75 | { 76 | struct jpeg_compress_struct cinfo; 77 | struct jpeg_error_mgr jerr; 78 | long unsigned int outSize = 0; 79 | uint8_t *outbuffer = NULL; 80 | JSAMPROW row_pointer[1]; 81 | 82 | cinfo.err = jpeg_std_error(&jerr); 83 | jpeg_create_compress(&cinfo); 84 | jpeg_mem_dest(&cinfo, &outbuffer, &outSize); 85 | cinfo.image_width = width; 86 | cinfo.image_height = height; 87 | cinfo.input_components = channels; // 3 / 1 88 | cinfo.in_color_space = color_space; // JCS_RGB / JCS_GRAYSCALE 89 | jpeg_set_defaults(&cinfo); 90 | jpeg_set_quality(&cinfo, quality, TRUE); // default 75 91 | jpeg_start_compress(&cinfo, TRUE); 92 | int row_stride = width * channels; 93 | while (cinfo.next_scanline < cinfo.image_height) 94 | { 95 | row_pointer[0] = (uint8_t *)&inData[cinfo.next_scanline * row_stride]; 96 | (void)jpeg_write_scanlines(&cinfo, row_pointer, 1); 97 | } 98 | jpeg_finish_compress(&cinfo); 99 | 100 | PyObject *bytes = PyBytes_FromStringAndSize((const char *)outbuffer, outSize); 101 | 102 | if (NULL != outbuffer) 103 | free(outbuffer), outbuffer = NULL; 104 | 105 | jpeg_destroy_compress(&cinfo); 106 | return bytes; 107 | } 108 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/example/maix_image_base_test.py: -------------------------------------------------------------------------------- 1 | 2 | from maix import image, display, camera 3 | import time 4 | 5 | 6 | import signal 7 | 8 | 9 | def handle_signal_z(signum, frame): 10 | print("APP OVER") 11 | exit(0) 12 | 13 | 14 | signal.signal(signal.SIGINT, handle_signal_z) 15 | 16 | 17 | def test_draw(): 18 | img = image.new(size=(240, 240), color=(255, 0, 0), mode="RGB") 19 | # draw_string 20 | img.draw_string(10, 200, "hello word!", scale=0.5, 21 | color=(0, 0, 255), thickness=1) 22 | display.show(img) 23 | time.sleep(1) 24 | # draw_line 25 | img.draw_line(10, 10, 10, 100, color=(0, 255, 0), thickness=1) 26 | display.show(img) 27 | time.sleep(1) 28 | # draw_rectangle 29 | img.draw_rectangle(20, 20, 50, 50, color=(0, 255, 0), thickness=1) 30 | display.show(img) 31 | time.sleep(1) 32 | # draw_circle 33 | img.draw_circle(100, 100, 20, color=(0, 255, 0), thickness=1) 34 | display.show(img) 35 | time.sleep(1) 36 | # draw_ellipse 37 | img.draw_ellipse(150, 150, 20, 50, 90, 0, 360, 38 | color=(0, 255, 0), thickness=1) 39 | display.show(img) 40 | time.sleep(1) 41 | 42 | 43 | test_draw() 44 | 45 | 46 | def test_img_copy(): 47 | img = image.new(color=(255, 0, 0)) 48 | print(img) 49 | display.show(img) 50 | time.sleep(0.5) 51 | imga = img.copy() 52 | print(imga) 53 | imga.draw_rectangle(0, 0, 240, 240, (0, 255, 0), -1) 54 | display.show(imga) 55 | 56 | 57 | test_img_copy() 58 | 59 | 60 | def test_set_pixel(): 61 | img = image.Image() 62 | img.new(color=(255, 0, 0)) 63 | for i in range(10, 50): 64 | for j in range(10, 20): 65 | img.set_pixel(i, j, (0, 0, 255)) 66 | display.show(img) 67 | 68 | 69 | test_set_pixel() 70 | 71 | 72 | def test_crop(): 73 | img = image.new(color=(255, 0, 0)) 74 | img.draw_string(100, 100, "nihao", color=(0, 0, 255)) 75 | display.show(img) 76 | mk = img.crop(90, 90, 100, 50) 77 | print(mk) 78 | display.show(mk.resize(240, 240)) 79 | 80 | 81 | test_crop() 82 | 83 | 84 | def test_draw_image(): 85 | img = image.new(color=(255, 0, 0)) 86 | img.draw_string(100, 100, "nihao", color=(0, 0, 255)) 87 | display.show(img) 88 | # time.sleep(0.5) 89 | mk = img.crop(90, 90, 100, 50) 90 | imga = image.new(color=(0, 255, 0)) 91 | imga.draw_image(mk, 10, 10) 92 | # imga.draw_image(imga) # py no-allow use self but libmaix support 93 | display.show(imga) 94 | 95 | 96 | test_draw_image() 97 | 98 | def test_rotate(): 99 | img = image.new(color=(255, 0, 0)) 100 | img.draw_string(100, 100, "nihao", color=(0, 0, 255)) 101 | for i in range(5): 102 | time.sleep(0.5) 103 | display.show(img.rotate(72)) 104 | 105 | 106 | test_rotate() 107 | 108 | 109 | def test_convert(): 110 | img = image.new(color=(255, 0, 0)) 111 | print(img) 112 | img.convert("L") 113 | print(img) 114 | img.convert("RGB") 115 | print(img) 116 | display.show(img) 117 | 118 | 119 | test_convert() 120 | 121 | def test_font_draw(): 122 | img = image.new(color=(255, 0, 0)) 123 | image.load_freetype("./smart/assets/fonts/Alibaba-PuHuiTi-Regular.ttf") 124 | s = "二进制例程" 125 | x, y = image.get_string_size(s, 3) 126 | print(x, y) 127 | img.draw_string(0, 240 - (y + 5), s, 3, (255, 255, 255)) # show left-button 128 | 129 | s = "二进制可执行文件示例" 130 | x, y = image.get_string_size(s, 2) 131 | print(x, y) 132 | img.draw_string(240 - x, 0, s, 2, (255, 255, 255)) # show right-up # wait fix 133 | 134 | display.show(img) 135 | time.sleep(1) 136 | 137 | img = image.new(color=(255, 0, 0)) 138 | 139 | image.load_freetype("./smart/assets/fonts/JosefinSans-Regular.ttf") 140 | s = "bin example" 141 | x, y = image.get_string_size(s, 3) 142 | print(x, y) 143 | img.draw_string(0, 240 - (y + 5), s, 3, (255, 255, 255)) # show left-button 144 | 145 | s = "run bin demo test" 146 | x, y = image.get_string_size(s, 2) 147 | print(x, y) 148 | img.draw_string(240 - x, 0, s, 2, (255, 255, 255)) # show right-up # wait fix 149 | 150 | display.show(img) 151 | time.sleep(1) 152 | 153 | test_font_draw() 154 | 155 | 156 | while True: 157 | display.show(camera.capture()) 158 | -------------------------------------------------------------------------------- /ext_modules/_maix_image/include/costom_imlib_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * 4 | * Copyright (c) 2013-2021 Ibrahim Abdelkader 5 | * Copyright (c) 2013-2021 Kwabena W. Agyeman 6 | * 7 | * This work is licensed under the MIT license, see the file LICENSE for details. 8 | * 9 | * Image library configuration. 10 | */ 11 | // #define IMLIB_CONFIG_H_FILE "costom_imlib_config.h" 12 | #ifndef __IMLIB_CONFIG_H__ 13 | #define __IMLIB_CONFIG_H__ 14 | #ifdef __cplusplus 15 | extern "C" 16 | { 17 | #endif 18 | // Enable Image I/O 19 | #define IMLIB_ENABLE_IMAGE_IO 20 | 21 | // Enable Image File I/O 22 | #define IMLIB_ENABLE_IMAGE_FILE_IO 23 | 24 | // Enable LAB LUT 25 | // #define IMLIB_ENABLE_LAB_LUT 26 | 27 | // Enable YUV LUT 28 | // #define IMLIB_ENABLE_YUV_LUT 29 | 30 | // Enable mean pooling 31 | #define IMLIB_ENABLE_MEAN_POOLING 32 | 33 | // Enable midpoint pooling 34 | #define IMLIB_ENABLE_MIDPOINT_POOLING 35 | 36 | // Enable binary ops 37 | #define IMLIB_ENABLE_BINARY_OPS 38 | 39 | // Enable math ops 40 | #define IMLIB_ENABLE_MATH_OPS 41 | 42 | // Enable flood_fill() 43 | #define IMLIB_ENABLE_FLOOD_FILL 44 | 45 | // Enable mean() 46 | #define IMLIB_ENABLE_MEAN 47 | 48 | // Enable median() 49 | #define IMLIB_ENABLE_MEDIAN 50 | 51 | // Enable mode() 52 | #define IMLIB_ENABLE_MODE 53 | 54 | // Enable midpoint() 55 | #define IMLIB_ENABLE_MIDPOINT 56 | 57 | // Enable morph() 58 | #define IMLIB_ENABLE_MORPH 59 | 60 | // Enable Gaussian 61 | #define IMLIB_ENABLE_GAUSSIAN 62 | 63 | // Enable Laplacian 64 | #define IMLIB_ENABLE_LAPLACIAN 65 | 66 | // Enable bilateral() 67 | #define IMLIB_ENABLE_BILATERAL 68 | 69 | // Enable cartoon() 70 | #define IMLIB_ENABLE_CARTOON 71 | 72 | // Enable linpolar() 73 | #define IMLIB_ENABLE_LINPOLAR 74 | 75 | // Enable logpolar() 76 | #define IMLIB_ENABLE_LOGPOLAR 77 | 78 | // Enable lens_corr() 79 | #define IMLIB_ENABLE_LENS_CORR 80 | 81 | // Enable find_apriltags() (64 KB) 82 | #define IMLIB_ENABLE_APRILTAGS 83 | 84 | // Enable fine find_apriltags() - (8-way connectivity versus 4-way connectivity) 85 | // #define IMLIB_ENABLE_FINE_APRILTAGS 86 | 87 | // Enable high res find_apriltags() - uses more RAM 88 | // #define IMLIB_ENABLE_HIGH_RES_APRILTAGS 89 | 90 | // Enable rotation_corr() 91 | #if defined(IMLIB_ENABLE_APRILTAGS) 92 | #define IMLIB_ENABLE_ROTATION_CORR 93 | #endif 94 | 95 | // Enable phasecorrelate() 96 | #if defined(IMLIB_ENABLE_ROTATION_CORR) 97 | #define IMLIB_ENABLE_FIND_DISPLACEMENT 98 | #endif 99 | 100 | // Enable find_rects() 101 | #if defined(IMLIB_ENABLE_ROTATION_CORR) 102 | #define IMLIB_ENABLE_FIND_RECTS 103 | #endif 104 | 105 | // Enable get_similarity() 106 | #define IMLIB_ENABLE_GET_SIMILARITY 107 | 108 | // Enable find_lines() 109 | #define IMLIB_ENABLE_FIND_LINES 110 | 111 | // Enable find_line_segments() 112 | #define IMLIB_ENABLE_FIND_LINE_SEGMENTS 113 | 114 | // Enable find_circles() 115 | #define IMLIB_ENABLE_FIND_CIRCLES 116 | 117 | 118 | // Enable find_qrcodes() (14 KB) 119 | #define IMLIB_ENABLE_QRCODES 120 | 121 | 122 | // Enable find_datamatrices() (26 KB) 123 | #define IMLIB_ENABLE_DATAMATRICES 124 | 125 | // Enable find_barcodes() (42 KB) 126 | #define IMLIB_ENABLE_BARCODES 127 | 128 | // Enable CMSIS NN 129 | // #if !defined(CUBEAI) 130 | // #define IMLIB_ENABLE_CNN 131 | // #endif 132 | 133 | // Enable Tensor Flow 134 | #if !defined(CUBEAI) 135 | #define IMLIB_ENABLE_TF 136 | #endif 137 | 138 | // Enable FAST (20+ KBs). 139 | #define IMLIB_ENABLE_FAST 140 | 141 | // Enable find_template() 142 | #define IMLIB_FIND_TEMPLATE 143 | 144 | // Enable find_lbp() 145 | // #define IMLIB_ENABLE_FIND_LBP 146 | 147 | // Enable find_keypoints() 148 | #define IMLIB_ENABLE_FIND_KEYPOINTS 149 | 150 | // Enable load, save and match descriptor 151 | #define IMLIB_ENABLE_DESCRIPTOR 152 | 153 | // Enable find_hog() 154 | //#define IMLIB_ENABLE_HOG 155 | 156 | // Enable selective_search() 157 | #define IMLIB_ENABLE_SELECTIVE_SEARCH 158 | 159 | // Enable PRINT 160 | // #define IMLIB_ENABLE_PRINT 161 | 162 | // FB Heap Block Size 163 | #define OMV_UMM_BLOCK_SIZE 256 164 | 165 | #define OMV_FB_ALLOC_SIZE (2 * 1024 * 1024) // minimum fb alloc size 166 | 167 | // Enable STM32 DMA2D 168 | // #define IMLIB_ENABLE_DMA2D 169 | #ifdef __cplusplus 170 | } 171 | #endif 172 | #endif //__IMLIB_CONFIG_H__ -------------------------------------------------------------------------------- /ext_modules/_maix_display/_dispay_pybind11.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "_maix_display.h" 3 | 4 | using namespace std; 5 | namespace py = pybind11; 6 | 7 | class _dispay_pybind11 8 | { 9 | private: 10 | public: 11 | string version = "0.2"; 12 | string name = "_maix_display"; 13 | _dispay_pybind11() 14 | { 15 | } 16 | ~_dispay_pybind11() 17 | { 18 | } 19 | string _maix_display_help() 20 | { 21 | return "MaixPy3 Display\n"; 22 | } 23 | }; 24 | 25 | PYBIND11_MODULE(_maix_display, m) 26 | { 27 | m.doc() = "This is MaixPy3 Display\n"; 28 | pybind11::class_<_dispay_pybind11>(m, "_maix_display") 29 | .def(pybind11::init()) 30 | .def_readonly("_VERSION_", &_dispay_pybind11::version) 31 | .def_readonly("_NAME_", &_dispay_pybind11::name) 32 | .def("help", &_dispay_pybind11::_maix_display_help); 33 | 34 | pybind11::class_<_Display>(m, "Display") 35 | .def(py::init()) 36 | .def_readonly("width", &_Display::width) 37 | .def_readonly("height", &_Display::height) 38 | .def_readonly("bpp", &_Display::bpp) 39 | .def("draw", &_Display::draw, py::arg("py_img"), py::arg("img_w") = 240, py::arg("img_w") = 240, py::arg("mode") = 3) 40 | .def("__enter__", &_Display::__enter__) 41 | .def("__exit__", &_Display::__exit__); 42 | } 43 | 44 | void v_close(_Display *tp) 45 | { 46 | if (NULL != tp->disp) 47 | libmaix_disp_destroy(&tp->disp); 48 | 49 | if (NULL != tp->display_image) 50 | libmaix_image_destroy(&tp->display_image); 51 | } 52 | 53 | void v_init(_Display *tp) 54 | { 55 | tp->disp = libmaix_disp_create(0); 56 | if (tp->disp == NULL) 57 | { 58 | v_close(tp); 59 | PyErr_SetString(PyExc_RuntimeError, "libmaix_disp_create err!"); 60 | throw py::error_already_set(); 61 | } 62 | tp->bpp = tp->disp->bpp; 63 | tp->width = tp->disp->width; 64 | tp->height = tp->disp->height; 65 | tp->display_image = libmaix_image_create(tp->width, tp->height, LIBMAIX_IMAGE_MODE_RGB888, LIBMAIX_IMAGE_LAYOUT_HWC, NULL, false); 66 | 67 | if (NULL == tp->display_image) 68 | { 69 | v_close(tp); 70 | PyErr_SetString(PyExc_RuntimeError, "libmaix_image_create err!"); 71 | throw py::error_already_set(); 72 | } 73 | } 74 | 75 | 76 | _Display::_Display() 77 | { 78 | v_init(this); 79 | } 80 | 81 | _Display::~_Display() 82 | { 83 | v_close(this); 84 | } 85 | 86 | pybind11::object _Display::draw(pybind11::object py_img, int img_w, int img_h, int mode) 87 | { 88 | string tmp; 89 | if (py::isinstance(py_img)) 90 | { 91 | tmp = py_img.cast(); 92 | this->display_image->data = (void *)(uint8_t *)tmp.c_str(); 93 | this->display_image->mode = libmaix_image_mode_t(mode); 94 | } 95 | else 96 | { 97 | auto PIL_ = py::module::import("PIL.Image").attr("Image"); 98 | if (py::isinstance(py_img, PIL_)) 99 | { 100 | auto tobytes = PIL_.attr("tobytes"); 101 | auto img_bytes = tobytes(py_img); 102 | tmp = img_bytes.cast(); 103 | this->display_image->data = (void *)(uint8_t *)tmp.c_str(); 104 | auto img_size = py_img.attr("size").cast>(); 105 | string tmp_mode = py_img.attr("mode").cast(); 106 | if (tmp_mode == "RGB") 107 | this->display_image->mode = LIBMAIX_IMAGE_MODE_RGB888; 108 | else // fit other format 109 | return py::none(); 110 | // this->display_image->mode = LIBMAIX_IMAGE_MODE_RGB888; 111 | img_w = img_size[0]; 112 | img_h = img_size[1]; 113 | } 114 | } 115 | 116 | this->display_image->width = img_w; 117 | this->display_image->height = img_h; 118 | 119 | if (NULL != this->disp) 120 | { 121 | if (!this->disp->width) this->disp->width = img_w; 122 | if (!this->disp->height) this->disp->height = img_h; 123 | // desktop will set (0, 0). 124 | if (this->disp->width >= img_w && this->disp->height >= img_h) 125 | { 126 | if (this->display_image->data != NULL) 127 | { 128 | this->disp->draw_image(this->disp, this->display_image); 129 | } 130 | } 131 | } 132 | return py::none(); 133 | } 134 | 135 | void _Display::close() 136 | { 137 | v_close(this); 138 | } 139 | 140 | void _Display::__enter__() 141 | { 142 | //do nothing... 143 | } 144 | 145 | void _Display::__exit__() 146 | { 147 | v_close(this); 148 | } 149 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_mud/src/py_maix_nn.c: -------------------------------------------------------------------------------- 1 | 2 | #include "py_maix_nn.h" 3 | #include "py_maix_nn_classifier.h" 4 | #include "py_maix_nn_FaceRecognize.h" 5 | #include "string.h" 6 | #include "libmaix_nn.h" 7 | 8 | static PyObject* _maix_nn_help() { 9 | return PyUnicode_FromString(_maix_nn_doc); 10 | } 11 | 12 | PyDoc_STRVAR(_maix_nn_load_doc, "load model, returen a nn.Model object\n"); 13 | 14 | static PyObject *_maix_nn_load(PyObject *self, PyObject *args, PyObject *kw_args) 15 | { 16 | /* parse args */ 17 | static char *kwlist[] = {"model_path", "opt", NULL}; 18 | 19 | PyObject *model_path = NULL; 20 | PyObject *opt = NULL; 21 | 22 | /* Get the buffer's memory */ 23 | if (!PyArg_ParseTupleAndKeywords(args, kw_args, "O|$O:load", kwlist, 24 | &model_path, &opt)) 25 | { 26 | return NULL; 27 | } 28 | /* new object */ 29 | PyObject* call_args = PyList_New(0); 30 | PyObject* call_keywords = PyDict_New(); 31 | PyObject* model_obj = PyMaix_NN_Model_Type.tp_new(&PyMaix_NN_Model_Type, call_args, call_keywords); 32 | Py_DECREF(call_args);Py_DECREF(call_keywords); 33 | if(!model_obj) 34 | { 35 | PyErr_NoMemory(); 36 | return NULL; 37 | } 38 | /* init model object */ 39 | call_args = Py_BuildValue("(O)", model_path); 40 | call_keywords = PyDict_New(); 41 | if( opt != NULL) 42 | { 43 | PyDict_SetItemString(call_keywords, "opt", opt); 44 | } 45 | PyObject *o_init_func = PyObject_GetAttrString(model_obj, "__init__"); 46 | PyObject* ret = PyObject_Call(o_init_func, call_args, call_keywords); 47 | // Py_DECREF(opt); 48 | Py_DECREF(call_args); 49 | Py_DECREF(call_keywords); 50 | Py_DECREF(o_init_func); 51 | if( ret == NULL) 52 | { 53 | return NULL; 54 | } 55 | 56 | return model_obj; 57 | } 58 | 59 | 60 | static PyMethodDef _maix_nn_methods[] = { 61 | {"help", (PyCFunction)_maix_nn_help, METH_NOARGS, _maix_nn_doc}, 62 | {"load", (PyCFunction)_maix_nn_load, METH_VARARGS | METH_KEYWORDS, _maix_nn_load_doc}, 63 | {NULL, NULL, 0, NULL} 64 | }; 65 | 66 | static struct PyModuleDef _maix_nn_module = { 67 | PyModuleDef_HEAD_INIT, 68 | _MAIX_NN_NAME_, /* Module name */ 69 | _maix_nn_doc, /* Module _maixMethods */ 70 | -1, /* size of per-interpreter state of the module, size of per-interpreter state of the module,*/ 71 | _maix_nn_methods, 72 | }; 73 | 74 | PyMODINIT_FUNC PyInit__maix_nn(void) 75 | { 76 | 77 | PyObject *module; 78 | 79 | module = PyModule_Create(&_maix_nn_module); 80 | PyObject *version = PyUnicode_FromString(_MAIX_NN_VERSION_); 81 | 82 | 83 | /* Set module version */ 84 | PyObject *dict = PyModule_GetDict(module); 85 | PyDict_SetItemString(dict, "__version__", version); 86 | Py_DECREF(version); 87 | 88 | /* Add class*/ 89 | // PyModule_AddObject(module, "Model", SpamError); 90 | 91 | /* init object(default value) */ 92 | if (PyType_Ready(&PyMaix_NN_Model_Type) < 0) { 93 | return NULL; 94 | } 95 | if (PyType_Ready(&PyMaix_NN_Decoder_Yolo2_Type) < 0) { 96 | return NULL; 97 | } 98 | if (PyType_Ready(&PyMaix_NN_app_Classifier_Type) < 0) { 99 | return NULL; 100 | } 101 | if (PyType_Ready(&PyMaix_NN_app_FaceRecognize_Type) < 0) { 102 | return NULL; 103 | } 104 | 105 | /* Add maix.nn.F module*/ 106 | PyObject *functional_module = PyModule_Create(&maix_nn_functional_module); 107 | PyModule_AddObject(module, "F", functional_module); 108 | Py_INCREF(functional_module); 109 | PyModule_AddObject(module, "functional", functional_module); 110 | 111 | /* Add maix.nn.decoder module, 112 | add maix.nn.decoder.Yolo2 class*/ 113 | PyObject *decoder_module = PyModule_Create(&maix_nn_decoder_module); 114 | Py_INCREF(&PyMaix_NN_Decoder_Yolo2_Type); 115 | PyModule_AddObject(decoder_module, "Yolo2", (PyObject*)&PyMaix_NN_Decoder_Yolo2_Type); 116 | PyModule_AddObject(module, "_decoder", decoder_module); 117 | 118 | /* Add maix.nn._app module, 119 | add maix.nn._app.classifier class*/ 120 | PyObject *app_module = PyModule_Create(&maix_nn_app_module); 121 | Py_INCREF(&PyMaix_NN_app_Classifier_Type); 122 | PyModule_AddObject(app_module, "Classifier", (PyObject*)&PyMaix_NN_app_Classifier_Type); 123 | Py_INCREF(&PyMaix_NN_app_FaceRecognize_Type); 124 | PyModule_AddObject(app_module, "FaceRecognize", (PyObject*)&PyMaix_NN_app_FaceRecognize_Type); 125 | PyModule_AddObject(module, "_app", app_module); 126 | 127 | return module; 128 | } -------------------------------------------------------------------------------- /tests/maix_v831/self_classifier.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # MaixPy3自学习脚本一 3 | # 功能说明:通过V831上的按键控制学习物体,并保存特征文件 4 | # 使用说明:开机后,前三次每次按下一次右键拍照保存一张图片到算法中,保存三个类别后,再按右键拍照则进行添加相似图片, 5 | # 相似图片添加15张。添加完成后将会自动进行训练。训练结束后会进入预测阶段。程序会打印出算法结果 6 | # 按下左键将会保存模型到本地文件。 7 | # 时间:2021年9月15日 8 | # 作者:Neutree dianjixz 9 | from maix import nn, camera, display 10 | import time 11 | from maix.nn.app.classifier import Classifier 12 | from evdev import InputDevice 13 | from select import select 14 | import threading 15 | 16 | 17 | class funation: 18 | model = { 19 | "param": "/home/model/resnet18_1000_awnn.param", 20 | "bin": "/home/model/resnet18_1000_awnn.bin" 21 | } 22 | options = { 23 | "model_type": "awnn", 24 | "inputs": { 25 | "input0": (224, 224, 3) 26 | }, 27 | "outputs": { 28 | "190": (1, 1, 512) 29 | }, 30 | "mean": [127.5, 127.5, 127.5], 31 | "norm": [0.0176, 0.0176, 0.0176], 32 | } 33 | class_num = 3 34 | sample_num = 3 35 | curr_class = 0 36 | curr_sample = 0 37 | fun_status = 0 38 | 39 | def __init__(self, device=None): 40 | self.device = device 41 | self.keys = InputDevice('/dev/input/event0') 42 | threading.Thread(target=self.load_mode).start() 43 | self.fun = [self.wait_run, self.train, self.predict] 44 | self.event = self.fun[self.fun_status] 45 | 46 | def __del__(self): 47 | del self.classifier 48 | del self.m 49 | print("-- del model") 50 | 51 | def get_key(self): 52 | r, w, x = select([self.keys], [], [], 0) 53 | if r: 54 | for event in self.keys.read(): 55 | if event.value == 1 and event.code == 0x02: # 右键 56 | return 1 57 | elif event.value == 1 and event.code == 0x03: # 左键 58 | return 2 59 | elif event.value == 2 and event.code == 0x03: # 左键连按 60 | return 3 61 | 62 | def load_mode(self): 63 | print("-- load model:", self.model) 64 | self.m = nn.load(self.model, opt=self.options) 65 | print("-- load ok") 66 | print("-- load classifier") 67 | self.classifier = Classifier( 68 | self.m, self.class_num, self.sample_num, 512, 224, 224) 69 | print("-- load ok") 70 | self.fun_status += 1 71 | self.event = self.fun[self.fun_status] 72 | 73 | def wait_run(self): 74 | display.show(camera.capture()) 75 | 76 | def train(self): 77 | img = camera.capture() 78 | key = self.get_key() 79 | if self.curr_class < self.class_num: 80 | if key == 1: 81 | print("add class") 82 | self.classifier.add_class_img(img.tobytes()) 83 | self.curr_class += 1 84 | img.draw_string(10, 0, "please add class", 1.5, (255, 0, 0), 2) 85 | img.draw_string(10, 30, "{} object".format( 86 | self.curr_class+1), 1.5, (255, 0, 0), 2) 87 | elif self.curr_sample < self.sample_num: 88 | if key == 1: 89 | print("add sample") 90 | self.classifier.add_sample_img(img.tobytes()) 91 | self.curr_sample += 1 92 | if self.curr_sample == self.sample_num: 93 | img.draw_string(10, 0, "train ...", 1.5, (255, 0, 0), 2) 94 | print("train ...") 95 | self.classifier.train() 96 | self.status = 1 97 | print("train end ...") 98 | self.fun_status += 1 99 | self.event = self.fun[self.fun_status] 100 | self.classifier.save("./module.bin") 101 | print("save success!") 102 | img.draw_string(10, 0, "add Sample:{}".format( 103 | self.curr_sample), 1.5, (255, 0, 0), 2) 104 | display.show(img) 105 | 106 | def predict(self): 107 | img = camera.capture() 108 | idx, distance = self.classifier.predict(img.tobytes()) 109 | img.draw_string(10, 0, "predict class: " + str(idx+1), 1.5, (255, 0, 0), 2) 110 | img.draw_string(10, 30, "conf: " + str(100-distance), 1.5, (255, 0, 0), 2) 111 | display.show(img) 112 | 113 | 114 | if __name__ == "__main__": 115 | import signal 116 | 117 | def handle_signal_z(signum, frame): 118 | print("APP OVER") 119 | exit(0) 120 | signal.signal(signal.SIGINT, handle_signal_z) 121 | camera.config(size=(224, 224)) 122 | start = funation() 123 | while True: 124 | start.event() 125 | -------------------------------------------------------------------------------- /ext_modules/libi2c/example/i2c_tools.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "i2c.h" 6 | 7 | void print_i2c_data(const unsigned char *data, size_t len) 8 | { 9 | int i = 0; 10 | 11 | for (i = 0; i < len; i++) { 12 | 13 | if (i % 16 == 0) { 14 | 15 | fprintf(stdout, "\n"); 16 | } 17 | 18 | fprintf(stdout, "%02x ", data[i]); 19 | } 20 | 21 | fprintf(stdout, "\n"); 22 | } 23 | 24 | 25 | int main(int argc, char **argv) 26 | { 27 | char i2c_dev_desc[128]; 28 | I2C_READ_HANDLE i2c_read_handle = i2c_read; 29 | I2C_WRITE_HANDLE i2c_write_handle = i2c_write; 30 | unsigned int addr = 0, iaddr_bytes = 0, page_bytes = 0, bus_num = -1; 31 | 32 | if (argc < 5) { 33 | 34 | fprintf(stdout, "Usage:%s [ioctl]\n" 35 | "Such as:\n" 36 | "\t24c02 i2c_test 1 0x50 1 8\n" 37 | "\t24c04 i2c_test 1 0x50 1 16\n" 38 | "\t24c64 i2c_test 1 0x50 2 32\n" 39 | "\t24c64 i2c_test 1 0x50 2 ioctl\n", argv[0]); 40 | exit(0); 41 | } 42 | 43 | /* Get i2c bus number */ 44 | if (sscanf(argv[1], "%u", &bus_num) != 1) { 45 | 46 | fprintf(stderr, "Can't parse i2c 'bus_num' [%s]\n", argv[1]); 47 | exit(-1); 48 | } 49 | 50 | /* Get i2c device address */ 51 | if (sscanf(argv[2], "0x%x", &addr) != 1) { 52 | 53 | fprintf(stderr, "Can't parse i2c 'dev_addr' [%s]\n", argv[2]); 54 | exit(-1); 55 | } 56 | 57 | /* Get i2c internal address bytes */ 58 | if (sscanf(argv[3], "%u", &iaddr_bytes) != 1) { 59 | 60 | fprintf(stderr, "Can't parse i2c 'iaddr_bytes' [%s]\n", argv[3]); 61 | exit(-2); 62 | } 63 | 64 | /* Get i2c page bytes number */ 65 | if (sscanf(argv[4], "%u", &page_bytes) != 1) { 66 | 67 | fprintf(stderr, "Can't parse i2c 'page_bytes' [%s]\n", argv[4]); 68 | exit(-2); 69 | } 70 | 71 | 72 | /* If specify ioctl using ioctl r/w i2c */ 73 | if (argc == 6 && (memcmp(argv[5], "ioctl", strlen("ioctl")) == 0)) { 74 | 75 | i2c_read_handle = i2c_ioctl_read; 76 | i2c_write_handle = i2c_ioctl_write; 77 | fprintf(stdout, "Using i2c_ioctl_oper r/w data\n"); 78 | } 79 | else { 80 | 81 | fprintf(stdout, "Using i2c_oper r/w data\n"); 82 | } 83 | 84 | /* Open i2c bus */ 85 | int bus; 86 | char bus_name[32]; 87 | memset(bus_name, 0, sizeof(bus_name)); 88 | 89 | if (snprintf(bus_name, sizeof(bus_name), "/dev/i2c-%u", bus_num) < 0) { 90 | 91 | fprintf(stderr, "Format i2c bus name error!\n"); 92 | exit(-3); 93 | } 94 | 95 | if ((bus = i2c_open(bus_name)) == -1) { 96 | 97 | fprintf(stderr, "Open i2c bus:%s error!\n", bus_name); 98 | exit(-3); 99 | } 100 | 101 | /* Init i2c device */ 102 | I2CDevice device; 103 | memset(&device, 0, sizeof(device)); 104 | i2c_init_device(&device); 105 | 106 | device.bus = bus; 107 | device.addr = addr & 0x3ff; 108 | device.page_bytes = page_bytes; 109 | device.iaddr_bytes = iaddr_bytes; 110 | 111 | /* Print i2c device description */ 112 | fprintf(stdout, "%s\n", i2c_get_device_desc(&device, i2c_dev_desc, sizeof(i2c_dev_desc))); 113 | 114 | size_t i; 115 | unsigned char buf[256]; 116 | size_t buf_size = sizeof(buf); 117 | memset(buf, 0, buf_size); 118 | 119 | /* I/O r/w 0x00 - 0xff */ 120 | if (i2c_read_handle == i2c_read) { 121 | 122 | for (i = 0; i < buf_size; i++) { 123 | 124 | buf[i] = i; 125 | } 126 | } 127 | /* ioctl r/w 0xff - 0x0 */ 128 | else { 129 | 130 | for (i = 0; i < buf_size; i++) { 131 | 132 | buf[i] = 0xff - i; 133 | } 134 | } 135 | 136 | /* Print before write */ 137 | fprintf(stdout, "Write data:\n"); 138 | print_i2c_data(buf, buf_size); 139 | 140 | if (i2c_write_handle(&device, 0x0, buf, buf_size) != buf_size) { 141 | 142 | fprintf(stderr, "Write i2c error!\n"); 143 | exit(-4); 144 | } 145 | 146 | fprintf(stdout, "\nWrite success, prepare read....\n"); 147 | 148 | /* Read */ 149 | usleep(100000); 150 | memset(buf, 0, buf_size); 151 | 152 | if (i2c_read_handle(&device, 0x0, buf, buf_size) != buf_size) { 153 | 154 | fprintf(stderr, "Read i2c error!\n"); 155 | exit(-5); 156 | } 157 | 158 | /* Print read result */ 159 | fprintf(stdout, "Read data:\n"); 160 | print_i2c_data(buf, buf_size); 161 | 162 | i2c_close(bus); 163 | return 0; 164 | } 165 | 166 | 167 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/src/py_maix_nn.c: -------------------------------------------------------------------------------- 1 | 2 | #include "py_maix_nn.h" 3 | #include "py_maix_nn_classifier.h" 4 | #include "py_maix_nn_FaceRecognize.h" 5 | 6 | #include "string.h" 7 | #include "libmaix_nn.h" 8 | 9 | 10 | static PyObject* _maix_nn_help() { 11 | return PyUnicode_FromString(_maix_nn_doc); 12 | } 13 | 14 | PyDoc_STRVAR(_maix_nn_load_doc, "load model, returen a nn.Model object\n"); 15 | static PyObject *_maix_nn_load(PyObject *self, PyObject *args, PyObject *kw_args) 16 | { 17 | /* parse args */ 18 | static char *kwlist[] = {"model_path", "opt", NULL}; 19 | 20 | PyObject *model_path = NULL; 21 | PyObject *opt = NULL; 22 | 23 | /* Get the buffer's memory */ 24 | if (!PyArg_ParseTupleAndKeywords(args, kw_args, "|OO:load", kwlist, 25 | &model_path, &opt)) 26 | { 27 | return NULL; 28 | } 29 | if(!model_path || !opt) 30 | { 31 | PyErr_SetString(PyExc_ValueError, "need mode_path and opt args"); 32 | return NULL; 33 | } 34 | /* new object */ 35 | PyObject* call_args = PyList_New(0); 36 | PyObject* call_keywords = PyDict_New(); 37 | PyObject* model_obj = PyMaix_NN_Model_Type.tp_new(&PyMaix_NN_Model_Type, call_args, call_keywords); 38 | Py_DECREF(call_args);Py_DECREF(call_keywords); 39 | if(!model_obj) 40 | { 41 | PyErr_NoMemory(); 42 | return NULL; 43 | } 44 | /* init model object */ 45 | 46 | call_args = Py_BuildValue("(O)", model_path); 47 | call_keywords = PyDict_New(); 48 | PyDict_SetItemString(call_keywords, "opt", opt); 49 | PyObject *o_init_func = PyObject_GetAttrString(model_obj, "__init__"); 50 | PyObject* ret = PyObject_Call(o_init_func, call_args, call_keywords); 51 | // Py_DECREF(opt); 52 | Py_DECREF(call_args); 53 | Py_DECREF(call_keywords); 54 | Py_DECREF(o_init_func); 55 | if( ret == NULL) 56 | { 57 | return NULL; 58 | } 59 | 60 | return model_obj; 61 | } 62 | 63 | static PyMethodDef _maix_nn_methods[] = { 64 | {"help", (PyCFunction)_maix_nn_help, METH_NOARGS, _maix_nn_doc}, 65 | {"load", (PyCFunction)_maix_nn_load, METH_VARARGS | METH_KEYWORDS, _maix_nn_load_doc}, 66 | {NULL, NULL, 0, NULL} 67 | }; 68 | 69 | static struct PyModuleDef _maix_nn_module = { 70 | PyModuleDef_HEAD_INIT, 71 | _MAIX_NN_NAME_, /* Module name */ 72 | _maix_nn_doc, /* Module _maixMethods */ 73 | -1, /* size of per-interpreter state of the module, size of per-interpreter state of the module,*/ 74 | _maix_nn_methods, 75 | }; 76 | 77 | PyMODINIT_FUNC PyInit__maix_nn(void) 78 | { 79 | 80 | PyObject *module; 81 | 82 | module = PyModule_Create(&_maix_nn_module); 83 | PyObject *version = PyUnicode_FromString(_MAIX_NN_VERSION_); 84 | 85 | 86 | /* Set module version */ 87 | PyObject *dict = PyModule_GetDict(module); 88 | PyDict_SetItemString(dict, "__version__", version); 89 | Py_DECREF(version); 90 | 91 | /* Add class*/ 92 | // PyModule_AddObject(module, "Model", SpamError); 93 | 94 | /* init object(default value) */ 95 | if (PyType_Ready(&PyMaix_NN_Model_Type) < 0) { 96 | return NULL; 97 | } 98 | if (PyType_Ready(&PyMaix_NN_Decoder_Yolo2_Type) < 0) { 99 | return NULL; 100 | } 101 | if (PyType_Ready(&PyMaix_NN_app_Classifier_Type) < 0) { 102 | return NULL; 103 | } 104 | if (PyType_Ready(&PyMaix_NN_app_FaceRecognize_Type) < 0) { 105 | return NULL; 106 | } 107 | 108 | /* Add maix.nn.F module*/ 109 | PyObject *functional_module = PyModule_Create(&maix_nn_functional_module); 110 | PyModule_AddObject(module, "F", functional_module); 111 | Py_INCREF(functional_module); 112 | PyModule_AddObject(module, "functional", functional_module); 113 | 114 | /* Add maix.nn.decoder module, 115 | add maix.nn.decoder.Yolo2 class*/ 116 | PyObject *decoder_module = PyModule_Create(&maix_nn_decoder_module); 117 | Py_INCREF(&PyMaix_NN_Decoder_Yolo2_Type); 118 | PyModule_AddObject(decoder_module, "Yolo2", (PyObject*)&PyMaix_NN_Decoder_Yolo2_Type); 119 | PyModule_AddObject(module, "_decoder", decoder_module); 120 | 121 | /* Add maix.nn._app module, 122 | add maix.nn._app.classifier class*/ 123 | PyObject *app_module = PyModule_Create(&maix_nn_app_module); 124 | Py_INCREF(&PyMaix_NN_app_Classifier_Type); 125 | PyModule_AddObject(app_module, "Classifier", (PyObject*)&PyMaix_NN_app_Classifier_Type); 126 | Py_INCREF(&PyMaix_NN_app_FaceRecognize_Type); 127 | PyModule_AddObject(app_module, "FaceRecognize", (PyObject*)&PyMaix_NN_app_FaceRecognize_Type); 128 | PyModule_AddObject(module, "_app", app_module); 129 | 130 | return module; 131 | } 132 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn_decoder/py_maix_nn_decoder_ctc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "libmaix_nn.h" 13 | #include "libmaix_nn_decoder.h" 14 | #include "libmaix_nn_decoder_ctc.h" 15 | // #include "libmaix_cv_image.h" 16 | namespace py = pybind11; 17 | 18 | typedef struct 19 | { 20 | libmaix_nn_decoder_ctc_config_t config; 21 | libmaix_nn_decoder_t *decoder; 22 | libmaix_nn_layer_t *fmap_out; 23 | libmaix_nn_decoder_ctc_result_t ctc_result; 24 | bool init; 25 | } DecoderCTCObject; 26 | 27 | class _ctc_decoder 28 | { 29 | private: 30 | public: 31 | DecoderCTCObject object; 32 | _ctc_decoder(std::vector output_shape); 33 | ~_ctc_decoder(); 34 | std::string decoder_CTC_str() 35 | { 36 | return std::string("CTC decoder object"); 37 | } 38 | py::object decoder_CTC_run(py::object fmap) 39 | { 40 | libmaix_err_t err = LIBMAIX_ERR_NONE; 41 | 42 | auto numpy_object_type = py::module::import("numpy").attr("ndarray"); 43 | std::string bytes_buffer; 44 | if (py::isinstance(fmap)) 45 | { 46 | 47 | bytes_buffer = fmap.cast(); 48 | this->object.fmap_out->data = (void *)(float *)bytes_buffer.c_str(); 49 | } 50 | else if (py::isinstance(fmap, numpy_object_type)) 51 | { 52 | auto tobytes = fmap.attr("tobytes"); 53 | bytes_buffer = tobytes().cast(); 54 | this->object.fmap_out->data = (void *)(float *)bytes_buffer.c_str(); 55 | 56 | } 57 | else 58 | { 59 | std::cout << "the output feature map only support bytes or ndarray" << std::endl; 60 | } 61 | 62 | 63 | 64 | err = this->object.decoder->decode(this->object.decoder, this->object.fmap_out, &this->object.ctc_result); 65 | 66 | if (err != LIBMAIX_ERR_NONE) 67 | { 68 | std::cout << "CTC decode is faild " << std::endl; 69 | } 70 | py::list idxs; 71 | for (int i = 0; i != this->object.ctc_result.length; i++) 72 | { 73 | 74 | int idx = int(this->object.ctc_result.no_repeat_idx[i]); 75 | idxs.append(idx); 76 | } 77 | 78 | return std::move(idxs); 79 | } 80 | }; 81 | 82 | _ctc_decoder::_ctc_decoder(std::vector output_shape) 83 | { 84 | libmaix_err_t err = LIBMAIX_ERR_NONE; 85 | 86 | this->object.config.N = output_shape[0]; 87 | this->object.config.C = output_shape[1]; 88 | this->object.config.T = output_shape[2]; 89 | this->object.config.classes_num = 68; 90 | this->object.config.lpr_max_lenght = 8; 91 | 92 | this->object.ctc_result.no_repeat_idx = (int *)malloc(sizeof(int) * this->object.config.lpr_max_lenght); 93 | if(!this->object.ctc_result.no_repeat_idx) 94 | this->object.init = false; 95 | 96 | 97 | this->object.fmap_out = (libmaix_nn_layer_t *)malloc(sizeof(libmaix_nn_layer_t)); 98 | if (!this->object.fmap_out) 99 | { 100 | std::cout << "allocate output layer faild" << std::endl; 101 | } 102 | this->object.fmap_out->w = output_shape[2]; 103 | this->object.fmap_out->h = output_shape[1]; 104 | this->object.fmap_out->c = output_shape[0]; 105 | this->object.fmap_out->dtype = LIBMAIX_NN_DTYPE_FLOAT; 106 | this->object.fmap_out->data = NULL; 107 | this->object.fmap_out->layout = LIBMAIX_NN_LAYOUT_CHW; 108 | 109 | this->object.decoder = libmaix_nn_decoder_ctc_create(); 110 | if (!this->object.decoder) 111 | { 112 | this->object.init = false; 113 | } 114 | 115 | err = this->object.decoder->init(this->object.decoder, &(this->object.config)); 116 | if (err != LIBMAIX_ERR_NONE) 117 | { 118 | this->object.init = false; 119 | printf("libmaix nn license_plate_location object init faild\n"); 120 | } 121 | else 122 | { 123 | this->object.init = true; 124 | printf("libmaix nn license_plate_location object init success\n"); 125 | } 126 | } 127 | 128 | _ctc_decoder::~_ctc_decoder() 129 | { 130 | if (this->object.decoder) 131 | { 132 | libmaix_nn_decoder_ctc_deinit(this->object.decoder); 133 | libmaix_nn_decoder_ctc_destroy(&this->object.decoder); 134 | } 135 | } 136 | 137 | PYBIND11_MODULE(_maix_nn_decoder_CTC, m) 138 | { 139 | pybind11::class_<_ctc_decoder>(m, "CTC") 140 | .def(pybind11::init>(), py::arg("output_shape")) 141 | .def("__str__", &_ctc_decoder::decoder_CTC_str) 142 | .def("run", &_ctc_decoder::decoder_CTC_run, py::arg("fmaps")); 143 | } 144 | -------------------------------------------------------------------------------- /ext_modules/_maix_camera/_camera_pybind.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "_maix_camera.h" 3 | 4 | using namespace std; 5 | namespace py = pybind11; 6 | 7 | class _Camera_pybind11 8 | { 9 | private: 10 | public: 11 | string version = "0.2"; 12 | string name = "_maix_Camera"; 13 | _Camera_pybind11() 14 | { 15 | } 16 | ~_Camera_pybind11() 17 | { 18 | cout << "_maix_Camera exit!" << endl; 19 | } 20 | string _maix_Camera_help() 21 | { 22 | return "MaixPy3 Camera\n"; 23 | } 24 | }; 25 | 26 | PYBIND11_MODULE(_maix_camera, m) 27 | { 28 | m.doc() = "This is MaixPy3 Camera\n"; 29 | pybind11::class_<_Camera_pybind11>(m, "_maix_camera") 30 | .def(pybind11::init()) 31 | .def_readonly("_VERSION_", &_Camera_pybind11::version) 32 | .def_readonly("_NAME_", &_Camera_pybind11::name) 33 | .def("help", &_Camera_pybind11::_maix_Camera_help, R"pbdoc(read()\n\nRead image(rgb888) bytes data from device.\n)pbdoc") 34 | .doc() = "_maix_Camera"; 35 | 36 | pybind11::class_<_camera>(m, "Camera") 37 | .def(py::init(), py::arg("w") = 240, py::arg("h") = 240, py::arg("dev_id") = 0, py::arg("m") = 0, py::arg("f") = 0) 38 | .def_readwrite("width", &_camera::width) 39 | .def_readwrite("height", &_camera::height) 40 | .def("read", &_camera::read) 41 | .def("close", &_camera::close, R"pbdoc(close()\n\nClose Camera device.\n)pbdoc") 42 | .def("__enter__", &_camera::__enter__) 43 | .def("__exit__", &_camera::__exit__) 44 | .doc() = "Camera(width, height,device_id) -> Camera object.\n"; 45 | } 46 | 47 | void v_close(_camera *tp) 48 | { 49 | #ifdef VirtualCamera 50 | cout << "virtual_camera close!" << endl; 51 | #else // VirtualCamera 52 | if (NULL != tp->cam) { 53 | libmaix_cam_destroy(&tp->cam); 54 | } 55 | libmaix_image_module_deinit(); 56 | libmaix_camera_module_deinit(); 57 | 58 | #endif //VirtualCamera else 59 | } 60 | 61 | void v_init(_camera *tp) 62 | { 63 | #ifdef VirtualCamera 64 | cout << "virtual_camera init success!" << endl; 65 | #else // VirtualCamera 66 | 67 | // printf("libmaix_camera_module_init %s:%s\r\n", __FILE__, __FUNCTION__); 68 | libmaix_camera_module_init(); 69 | // printf("libmaix_image_module_init %s:%s\r\n", __FILE__, __FUNCTION__); 70 | libmaix_image_module_init(); 71 | tp->rgb_img = NULL; 72 | tp->cam = libmaix_cam_create(tp->dev_id, tp->width, tp->height, tp->m, tp->f); 73 | if (NULL != tp->cam) 74 | { 75 | int ret = tp->cam->start_capture(tp->cam); 76 | if (0 == ret) 77 | { 78 | return; 79 | } 80 | else 81 | { 82 | PyErr_SetString(PyExc_RuntimeError, "cam start capture err!"); 83 | throw py::error_already_set(); 84 | } 85 | } 86 | else 87 | { 88 | PyErr_SetString(PyExc_RuntimeError, "libmaix_cam_create err!"); 89 | throw py::error_already_set(); 90 | } 91 | v_close(tp); 92 | 93 | #endif // VirtualCamera 94 | } 95 | 96 | _camera::_camera(int w, int h, int dev_id, int m, int f) 97 | { 98 | this->width = w; 99 | this->height = h; 100 | this->dev_id = dev_id; 101 | this->m = m; 102 | this->f = f; 103 | v_init(this); 104 | } 105 | 106 | _camera::~_camera() 107 | { 108 | v_close(this); 109 | } 110 | // "read()\n\nRead image(rgb888) bytes data from device.\n" 111 | pybind11::list _camera::read() 112 | { 113 | py::list return_val; 114 | #ifdef VirtualCamera 115 | return_val.append(0); 116 | return_val.append(py::none()); 117 | #else 118 | int ret = LIBMAIX_ERR_NONE; 119 | for (size_t i = 0; i < 5; i++) 120 | { 121 | ret = this->cam->capture_image(this->cam, &this->rgb_img); 122 | // not ready, sleep to release CPU 123 | if (ret == LIBMAIX_ERR_NOT_READY) 124 | { 125 | usleep(25 * 1000); 126 | continue; 127 | } 128 | break; 129 | } 130 | /* Copy data to bytearray and return */ 131 | 132 | if (NULL != this->rgb_img) 133 | { 134 | return_val.append(true); 135 | py::bytes tmp((char *)this->rgb_img->data, this->rgb_img->width * this->rgb_img->height * 3); 136 | return_val.append(tmp); 137 | } 138 | else 139 | { 140 | return_val.append(false); 141 | return_val.append(py::none()); 142 | } 143 | 144 | 145 | 146 | #endif // VirtualCamera 147 | return return_val; 148 | } 149 | 150 | void _camera::close() 151 | { 152 | v_close(this); 153 | } 154 | 155 | void _camera::__enter__() 156 | { 157 | //do nothing... 158 | } 159 | 160 | void _camera::__exit__() 161 | { 162 | v_close(this); 163 | } 164 | 165 | // string v831_camera::str() 166 | // { 167 | // return string(__FILE__); 168 | // } 169 | -------------------------------------------------------------------------------- /ext_modules/libi2c/README.md: -------------------------------------------------------------------------------- 1 | libi2c 2 | ======= 3 | 4 | Linux userspace i2c library. 5 | 6 | 7 | ## Features 8 | 9 | - Support C/C++ and Python. 10 | 11 | - Support Python2+, Python3+ 12 | 13 | - Support multiple bus and devices. 14 | 15 | - Support 7-bit and 10-bit i2c slave address. 16 | 17 | - Support 1 - 4 byte internal address, auto convert. 18 | 19 | - Provide read/write/ioctl functions to operate i2c device. 20 | 21 | - Support 8/16/32/64/128/256 bytes page aligned write, read/write length are unlimited. 22 | 23 | - Using ioctl functions operate i2c can ignore i2c device ack signal and internal address. 24 | 25 | 26 | ## Installation 27 | 28 | sudo python setup.py install 29 | 30 | or 31 | 32 | sudo make install 33 | 34 | or 35 | 36 | sudo make install PYTHON=pythonX.X 37 | 38 | ## Interface 39 | 40 | i2c_ioctl_write (once max 16 bytes) are more efficient than i2c_write (once max 4 bytes). 41 | 42 | /* Close i2c bus */ 43 | void i2c_close(int bus); 44 | 45 | /* Open i2c bus, return i2c bus fd */ 46 | int i2c_open(const char *bus_name); 47 | 48 | /* I2C file I/O read, write */ 49 | ssize_t i2c_read(const I2CDevice *device, unsigned int iaddr, void *buf, size_t len); 50 | ssize_t i2c_write(const I2CDevice *device, unsigned int iaddr, const void *buf, size_t len); 51 | 52 | /* I2c ioctl read, write can set i2c flags */ 53 | ssize_t i2c_ioctl_read(const I2CDevice *device, unsigned int iaddr, void *buf, size_t len); 54 | ssize_t i2c_ioctl_write(const I2CDevice *device, unsigned int iaddr, const void *buf, size_t len); 55 | 56 | ## Data structure 57 | 58 | **C/C++** 59 | 60 | typedef struct i2c_device { 61 | int bus; /* I2C Bus fd, return from i2c_open */ 62 | unsigned short addr; /* I2C device(slave) address */ 63 | unsigned char tenbit; /* I2C is 10 bit device address */ 64 | unsigned char delay; /* I2C internal operate delay, unit millisecond */ 65 | unsigned short flags; /* I2C i2c_ioctl_read/write flags */ 66 | unsigned int page_bytes; /* I2C max number of bytes per page, 1K/2K 8, 4K/8K/16K 16, 32K/64K 32 etc */ 67 | unsigned int iaddr_bytes; /* I2C device internal(word) address bytes, such as: 24C04 1 byte, 24C64 2 bytes */ 68 | }I2CDevice; 69 | 70 | **Python** 71 | 72 | I2CDevice object 73 | I2CDevice(bus, addr, tenbit=False, iaddr_bytes=1, page_bytes=8, delay=1, flags=0) 74 | tenbit, delay, flags, page_bytes, iaddr_bytes are attributes can setter/getter after init 75 | 76 | required args: bus, addr. 77 | optional args: tenbit(defult False, 7-bit), delay(defualt 1ms), flags(defualt 0), iaddr_bytes(defualt 1 byte internal address), page_bytes(default 8 bytes per page). 78 | 79 | 80 | ## C/C++ Usage 81 | 82 | **1. First call `i2c_open` open i2c bus.** 83 | 84 | int bus; 85 | 86 | /* Open i2c bus /dev/i2c-0 */ 87 | if ((bus = i2c_open("/dev/i2c-0")) == -1) { 88 | 89 | /* Error process */ 90 | } 91 | 92 | **2. Second fill `I2CDevice` struct, prepare read or write.** 93 | 94 | I2CDevice device; 95 | memset(&device, 0, sizeof(device)); 96 | 97 | /* 24C04 */ 98 | device.bus = bus; /* Bus 0 */ 99 | device.addr = 0x50; /* Slave address is 0x50, 7-bit */ 100 | device.iaddr_bytes = 1; /* Device internal address is 1 byte */ 101 | device.page_bytes = 16; /* Device are capable of 16 bytes per page */ 102 | 103 | **3. Call `i2c_read/write` or `i2c_ioctl_read/write` read or write i2c device.** 104 | 105 | unsigned char buffer[256]; 106 | ssize_t size = sizeof(buffer); 107 | memset(buffer, 0, sizeof(buffer)); 108 | 109 | /* From i2c 0x0 address read 256 bytes data to buffer */ 110 | if ((i2c_read(&device, 0x0, buffer, size)) != size) { 111 | 112 | /* Error process */ 113 | } 114 | 115 | **4. Close i2c bus `i2c_close(bus)`.** 116 | 117 | i2c_close(bus); 118 | 119 | ## Python Usage 120 | 121 | import ctypes 122 | import pylibi2c 123 | 124 | # Open i2c device @/dev/i2c-0, addr 0x50. 125 | i2c = pylibi2c.I2CDevice('/dev/i2c-0', 0x50) 126 | 127 | # Open i2c device @/dev/i2c-0, addr 0x50, 16bits internal address 128 | i2c = pylibi2c.I2CDevice('/dev/i2c-0', 0x50, iaddr_bytes=2) 129 | 130 | # Set delay 131 | i2c.delay = 10 132 | 133 | # Set page_bytes 134 | i2c.page_bytes = 16 135 | 136 | # Set flags 137 | i2c.flags = pylibi2c.I2C_M_IGNORE_NAK 138 | 139 | # Python2 140 | buf = bytes(bytearray(256)) 141 | 142 | # Python3 143 | buf = bytes(256) 144 | 145 | # Write data to i2c, buf must be read-only type 146 | size = i2c.write(0x0, buf) 147 | 148 | # From i2c 0x0(internal address) read 256 bytes data, using ioctl_read. 149 | data = i2c.ioctl_read(0x0, 256) 150 | 151 | ## Notice 152 | 153 | 1. If i2c device do not have internal address, please use `i2c_ioctl_read/write` function for read/write, set`'iaddr_bytes=0`. 154 | 155 | 2. If want ignore i2c device nak signal, please use `i2c_ioctl_read/write` function, set I2CDevice.falgs as `I2C_M_IGNORE_NCK`. 156 | -------------------------------------------------------------------------------- /maix/pwm.py: -------------------------------------------------------------------------------- 1 | """Linux PWM driver sysfs interface""" 2 | 3 | import os 4 | __author__ = 'Scott Ellis' 5 | __version__ = '1.0' 6 | __license__ = 'New BSD' 7 | __copyright__ = 'Copyright (c) 2016 Scott Ellis' 8 | 9 | from types import ( 10 | TracebackType, 11 | ) 12 | 13 | from typing import ( 14 | Optional, 15 | Type, 16 | ) 17 | 18 | class PWM(object): 19 | """ 20 | A class to work with the Linux PWM driver sysfs interface 21 | """ 22 | 23 | def __init__(self, channel: int = 0, chip: int = 0) -> None: 24 | """ Specify channel and chip when creating an instance 25 | The Linux kernel driver exports a sysfs interface like this 26 | /sys/class/pwm/pwmchip/pwm 27 | A can have multiple . 28 | The channel and chip are determined by the kernel driver. 29 | For example the two PWM timers from the RPi kernel driver 30 | show up like this 31 | /sys/class/pwm/pwmchip0/pwm0 32 | /sys/class/pwm/pwmchip0/pwm1 33 | To use the RPi timers create instances this way 34 | pwm0 = PWM(0) or PWM(0,0) 35 | pwm1 = PWM(1) or PWM(1,0) 36 | """ 37 | self._channel = channel 38 | self._chip = chip 39 | self.base = '/sys/class/pwm/pwmchip{:d}'.format(self._chip) 40 | self.path = self.base + '/pwm{:d}'.format(self._channel) 41 | if not os.path.isdir(self.base): 42 | raise FileNotFoundError('Directory not found: ' + self.base) 43 | 44 | # enable class as a context manager 45 | def __enter__(self) -> 'PWM': 46 | self.export() 47 | return self 48 | 49 | def __exit__(self, 50 | exc_type: Optional[Type[BaseException]], 51 | exc_value: Optional[BaseException], 52 | traceback: Optional[TracebackType]) -> None: 53 | self.enable = False 54 | self.inversed = False 55 | self.unexport() 56 | return 57 | 58 | def export(self) -> None: 59 | """Export the channel for use through the sysfs interface. 60 | Required before first use. 61 | """ 62 | if not os.path.isdir(self.path): 63 | with open(self.base + '/export', 'w') as f: 64 | f.write('{:d}'.format(self._channel)) 65 | 66 | def unexport(self) -> None: 67 | """Unexport the channel. 68 | The sysfs interface is no longer usable until it is exported again. 69 | """ 70 | if os.path.isdir(self.path): 71 | with open(self.base + '/unexport', 'w') as f: 72 | f.write('{:d}'.format(self._channel)) 73 | 74 | @property 75 | def channel(self) -> int: 76 | """The channel used by this instance. 77 | Read-only, set in the constructor. 78 | """ 79 | return self._channel 80 | 81 | @property 82 | def chip(self) -> int: 83 | """The chip used by this instance. 84 | Read-only, set in the constructor. 85 | """ 86 | return self._chip 87 | 88 | @property 89 | def period(self) -> int: 90 | """The period of the pwm timer in nanoseconds.""" 91 | with open(self.path + '/period', 'r') as f: 92 | value = f.readline().strip() 93 | 94 | return int(value) 95 | 96 | @period.setter 97 | def period(self, value: int) -> None: 98 | with open(self.path + '/period', 'w') as f: 99 | f.write('{:d}'.format(value)) 100 | 101 | @property 102 | def duty_cycle(self) -> int: 103 | """The duty_cycle (the ON pulse) of the timer in nanoseconds.""" 104 | with open(self.path + '/duty_cycle', 'r') as f: 105 | value = f.readline().strip() 106 | 107 | return int(value) 108 | 109 | @duty_cycle.setter 110 | def duty_cycle(self, value: int) -> None: 111 | with open(self.path + '/duty_cycle', 'w') as f: 112 | f.write('{:d}'.format(value)) 113 | 114 | @property 115 | def enable(self) -> bool: 116 | """Enable or disable the timer, boolean""" 117 | with open(self.path + '/enable', 'r') as f: 118 | value = f.readline().strip() 119 | 120 | return True if value == '1' else False 121 | 122 | @enable.setter 123 | def enable(self, value: bool) -> None: 124 | with open(self.path + '/enable', 'w') as f: 125 | if value: 126 | f.write('1') 127 | else: 128 | f.write('0') 129 | 130 | @property 131 | def inversed(self) -> bool: 132 | """normal polarity or inversed, boolean""" 133 | with open(self.path + '/polarity', 'r') as f: 134 | value = f.readline().strip() 135 | 136 | return True if value == 'inversed' else False 137 | 138 | @inversed.setter 139 | def inversed(self, value: bool) -> None: 140 | with open(self.path + '/polarity', 'w') as f: 141 | if value: 142 | f.write('inversed') 143 | else: 144 | f.write('normal') 145 | 146 | 147 | -------------------------------------------------------------------------------- /tests/maix_v831/usage_v831_watchdog.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | """Provides Linux kernel Watchdog interface. 6 | https://www.kernel.org/doc/Documentation/watchdog/watchdog-api.txt 7 | """ 8 | 9 | import array 10 | import fcntl 11 | import struct 12 | 13 | IO_WRITE = 0x40000000 14 | IO_READ = 0x80000000 15 | IO_READ_WRITE = 0xC0000000 16 | IO_SIZE_INT = 0x00040000 17 | IO_SIZE_40 = 0x00280000 18 | IO_TYPE_WATCHDOG = ord('W') << 8 19 | 20 | WDR_INT = IO_READ | IO_SIZE_INT | IO_TYPE_WATCHDOG 21 | WDR_40 = IO_READ | IO_SIZE_40 | IO_TYPE_WATCHDOG 22 | WDWR_INT = IO_READ_WRITE | IO_SIZE_INT | IO_TYPE_WATCHDOG 23 | 24 | WDIOC_GETSUPPORT = 0 | WDR_40 25 | WDIOC_GETSTATUS = 1 | WDR_INT 26 | WDIOC_GETBOOTSTATUS = 2 | WDR_INT 27 | WDIOC_GETTEMP = 3 | WDR_INT 28 | WDIOC_SETOPTIONS = 4 | WDWR_INT 29 | WDIOC_KEEPALIVE = 5 | WDR_INT 30 | WDIOC_SETTIMEOUT = 6 | WDWR_INT 31 | WDIOC_GETTIMEOUT = 7 | WDR_INT 32 | WDIOC_SETPRETIMEOUT = 8 | WDWR_INT 33 | WDIOC_GETPRETIMEOUT = 9 | WDR_INT 34 | WDIOC_GETTIMELEFT = 10 | WDR_INT 35 | 36 | WDIOF_OVERHEAT = 0x0001 37 | WDIOF_FANFAULT = 0x0002 38 | WDIOF_EXTERN1 = 0x0004 39 | WDIOF_EXTERN2 = 0x0008 40 | WDIOF_POWERUNDER = 0x0010 41 | WDIOF_CARDRESET = 0x0020 42 | WDIOF_POWEROVER = 0x0040 43 | WDIOF_SETTIMEOUT = 0x0080 44 | WDIOF_MAGICCLOSE = 0x0100 45 | WDIOF_PRETIMEOUT = 0x0200 46 | WDIOF_ALARMONLY = 0x0400 47 | WDIOF_KEEPALIVEPING = 0x8000 48 | 49 | WDIOS_DISABLECARD = 0x0001 50 | WDIOS_ENABLECARD = 0x0002 51 | WDIOS_TEMPPANIC = 0x0004 52 | 53 | WATCHDOG_DEVICE = '/dev/watchdog' 54 | WATCHDOG_STOP = 'V' 55 | WATCHDOG_START = 'S' 56 | 57 | 58 | class Watchdog: 59 | """Linux Kernel watchdog class.""" 60 | 61 | def __init__(self, stop=True): 62 | super(Watchdog, self).__init__() 63 | self.fd = open(WATCHDOG_DEVICE, 'w') 64 | self.stop = stop 65 | if stop: 66 | self.Stop() 67 | 68 | def __del__(self) -> None: # for v831 69 | try: 70 | self.fd.close() 71 | import os 72 | os.system("echo V > " + WATCHDOG_DEVICE) 73 | except Exception as e: 74 | pass 75 | 76 | def Stop(self): 77 | self.fd.write(WATCHDOG_STOP) 78 | 79 | def Start(self): 80 | self.stop = False 81 | self.fd.write(WATCHDOG_START) 82 | 83 | def _IoctlInt(self, cmd, write_value=0): 84 | """Writes and reads integer. 85 | Args: 86 | cmd: ioctl command contains read/write flag. 87 | write_value: the 32bit value to write. 88 | Returns: 89 | 32bit integer from ioctl mutable buffer. 90 | """ 91 | buf = array.array('I', [write_value]) 92 | start_temporary = self.stop 93 | # For stopped watchdog, we need to start it temporary to set a value as 94 | # some hardware accepts commands only when watchdog is running. 95 | if start_temporary: 96 | self.Start() 97 | fcntl.ioctl(self.fd, cmd, buf, True) 98 | if start_temporary: 99 | self.Stop() 100 | return buf[0] 101 | 102 | def GetStatus(self): 103 | """Gets watchdog status flags. 104 | The status and boot status are used to fetch the current status, and the 105 | status at the last reboot. Enabled options are described in GetSupport() 106 | return value. Status/option WDIOF_flags: 107 | WDIOF_OVERHEAT: CPU overheat triggered. 108 | WDIOF_FANFAULT: Fan failed triggered. 109 | WDIOF_EXTERN1/2: External source triggered. 110 | WDIOF_POWEROVER: Overvoltage detected. 111 | WDIOF_KEEPALIVEPING: Got a keep alive ping after last query. 112 | WDIOF_TIMEOUT: Reset due to timeout. 113 | """ 114 | return self._IoctlInt(WDIOC_GETSTATUS) 115 | 116 | def GetBootStatus(self): 117 | return self._IoctlInt(WDIOC_GETBOOTSTATUS) 118 | 119 | def GetTemp(self): 120 | return self._IoctlInt(WDIOC_GETTEMP) 121 | 122 | def SetOptions(self, options): 123 | return self._IoctlInt(WDIOC_SETOPTIONS, options) 124 | 125 | def KeepAlive(self): 126 | if self.stop: 127 | self.Start() 128 | return self._IoctlInt(WDIOC_KEEPALIVE) 129 | 130 | def SetTimeout(self, timeout): 131 | timeout = int(timeout) 132 | if timeout <= 0: 133 | raise ValueError('timeout <= 0') 134 | return self._IoctlInt(WDIOC_SETTIMEOUT, timeout) 135 | 136 | def GetTimeout(self): 137 | return self._IoctlInt(WDIOC_GETTIMEOUT) 138 | 139 | def SetPreTimeout(self, timeout): 140 | timeout = int(timeout) 141 | if timeout <= 0 or timeout > 16: 142 | raise ValueError('0 < timeout <= 16') 143 | return self._IoctlInt(WDIOC_SETPRETIMEOUT, timeout) 144 | 145 | def GetPreTimeout(self): 146 | return self._IoctlInt(WDIOC_GETPRETIMEOUT) 147 | 148 | def GetTimeLeft(self): 149 | return self._IoctlInt(WDIOC_GETTIMELEFT) 150 | 151 | if __name__ == '__main__': 152 | import wtd 153 | t = wtd.Watchdog() 154 | t.SetTimeout(1) 155 | import time 156 | t.KeepAlive() 157 | time.sleep(0.5) 158 | t.KeepAlive() 159 | time.sleep(0.5) 160 | t.__del__() 161 | del t 162 | t = wtd.Watchdog() 163 | del t 164 | t = wtd.Watchdog() 165 | t.SetTimeout(2) 166 | time.sleep(2) 167 | del t 168 | 169 | -------------------------------------------------------------------------------- /ext_modules/_maix_nn/src/py_maix_nn_funtional.c: -------------------------------------------------------------------------------- 1 | 2 | #include "Python.h" 3 | #include "py_maix_nn.h" 4 | 5 | #include 6 | #include 7 | 8 | static void maix_nn_functional_softmax_float32(float *data, int n, float *out, int stride) 9 | { 10 | int i; 11 | float sum = 0; 12 | float largest_i = data[0]; 13 | if(!out) 14 | { 15 | out = data; 16 | } 17 | 18 | for (i = 0; i < n; ++i) 19 | { 20 | if (data[i * stride] > largest_i) 21 | largest_i = data[i * stride]; 22 | } 23 | for (i = 0; i < n; ++i) 24 | { 25 | float value = expf(data[i * stride] - largest_i); 26 | sum += value; 27 | out[i * stride] = value; 28 | } 29 | for (i = 0; i < n; ++i) 30 | { 31 | out[i * stride] /= sum; 32 | } 33 | } 34 | 35 | static void maix_nn_functional_softmax_double(double *data, int n, double *out, int stride) 36 | { 37 | int i; 38 | double sum = 0; 39 | double largest_i = data[0]; 40 | if(!out) 41 | { 42 | out = data; 43 | } 44 | 45 | for (i = 0; i < n; ++i) 46 | { 47 | if (data[i * stride] > largest_i) 48 | largest_i = data[i * stride]; 49 | } 50 | for (i = 0; i < n; ++i) 51 | { 52 | double value = expf(data[i * stride] - largest_i); 53 | sum += value; 54 | out[i * stride] = value; 55 | } 56 | for (i = 0; i < n; ++i) 57 | { 58 | out[i * stride] /= sum; 59 | } 60 | } 61 | 62 | PyDoc_STRVAR(functional_softmax_doc, "softmax function.\n"); 63 | static PyObject* functional_softmax(PyObject *self, PyObject *args, PyObject *kw_args) 64 | { 65 | PyObject *o_input = NULL; 66 | int dim = -1; 67 | static char *kwlist[] = {"input", "dim", NULL}; 68 | /* Get the buffer's memory */ 69 | if (!PyArg_ParseTupleAndKeywords(args, kw_args, "O|$p:forward", kwlist, 70 | &o_input, &dim)) 71 | { 72 | return NULL; 73 | } 74 | if(dim >=0 ) //TODO: 75 | { 76 | PyErr_SetString(PyExc_NotImplementedError, "not support dim arg yet"); 77 | return NULL; 78 | } 79 | PyObject* m_numpy = PyImport_ImportModule("numpy"); 80 | if(!m_numpy) 81 | { 82 | PyErr_SetString(PyExc_EnvironmentError, "need numpy module"); 83 | return NULL; 84 | } 85 | PyObject* o_ndarray = PyObject_GetAttrString(m_numpy, "ndarray"); 86 | if(o_ndarray == NULL) 87 | { 88 | return NULL; 89 | } 90 | if((void*)o_input->ob_type == (void*)o_ndarray) 91 | { 92 | Py_DECREF(o_ndarray); 93 | int dtype = -1; 94 | PyObject* o_dtype = PyObject_GetAttrString(o_input, "dtype"); 95 | if(o_dtype == NULL) 96 | { 97 | return NULL; 98 | } 99 | PyObject* o_dtype_name = PyObject_GetAttrString(o_dtype, "name"); 100 | Py_DECREF(o_dtype); 101 | if(o_dtype_name == NULL) 102 | { 103 | return NULL; 104 | } 105 | char* dtype_name = PyUnicode_DATA(o_dtype_name); 106 | if(strcmp(dtype_name, "float32") == 0) 107 | { 108 | dtype = 1; 109 | } 110 | else if(strcmp(dtype_name, "float64") == 0) 111 | { 112 | dtype = 2; 113 | } 114 | else 115 | { 116 | Py_DECREF(o_dtype_name); 117 | PyErr_SetString(PyExc_ValueError, "only support float32 and float64 dtype"); 118 | return NULL; 119 | } 120 | PyObject* o_bytes = PyObject_CallMethod(o_input, "tobytes", NULL); 121 | if(o_bytes == NULL) 122 | { 123 | Py_DECREF(o_dtype_name); 124 | return NULL; 125 | } 126 | Py_ssize_t bytes_len = PyBytes_Size(o_bytes); 127 | char* bytes = PyBytes_AsString(o_bytes); 128 | switch(dtype) 129 | { 130 | case 1: //float32 131 | maix_nn_functional_softmax_float32((float*)bytes, bytes_len/4, NULL, 1); 132 | break; 133 | case 2: //float64 134 | maix_nn_functional_softmax_double((double*)bytes, bytes_len/4, NULL, 1); 135 | break; 136 | default: 137 | assert(false); // should never here 138 | return NULL; 139 | } 140 | PyObject *call_args = Py_BuildValue("(O)", o_bytes); 141 | PyObject *call_keywords = PyDict_New(); 142 | PyDict_SetItemString(call_keywords, "dtype", o_dtype_name); 143 | PyObject* o_result_numpy = PyObject_Call(PyObject_GetAttrString(m_numpy, "frombuffer"), call_args, call_keywords); 144 | Py_DECREF(call_args); 145 | Py_DECREF(call_keywords); 146 | Py_DECREF(o_dtype_name); 147 | Py_DECREF(o_bytes); 148 | return o_result_numpy; 149 | } 150 | else 151 | { 152 | Py_DECREF(o_ndarray); 153 | PyErr_SetString(PyExc_NotImplementedError, "only support numpy object"); 154 | return NULL; 155 | } 156 | } 157 | 158 | static PyMethodDef _maix_nn_functional_methods[] = { 159 | {"softmax", (PyCFunction)functional_softmax, METH_VARARGS | METH_KEYWORDS, functional_softmax_doc}, 160 | {NULL, NULL, 0, NULL} 161 | }; 162 | 163 | 164 | struct PyModuleDef maix_nn_functional_module = { 165 | PyModuleDef_HEAD_INIT, 166 | "functional", /* Module name */ 167 | _maix_nn_functional_doc, /* Module _maixMethods */ 168 | -1, /* size of per-interpreter state of the module, size of per-interpreter state of the module,*/ 169 | _maix_nn_functional_methods, 170 | }; 171 | 172 | 173 | --------------------------------------------------------------------------------