Refactor: Rename NanoKVM to BatchuKVM and update server URL
This commit is contained in:
77
support/sg2002/additional/vision/CMakeLists.txt
Normal file
77
support/sg2002/additional/vision/CMakeLists.txt
Normal file
@@ -0,0 +1,77 @@
|
||||
# Config enable component2 or not in Kconfig
|
||||
################# Add include #################
|
||||
list(APPEND ADD_INCLUDE "include"
|
||||
"include/base"
|
||||
)
|
||||
if(PLATFORM_LINUX)
|
||||
list(APPEND ADD_PRIVATE_INCLUDE "port/linux")
|
||||
elseif(PLATFORM_MAIXCAM)
|
||||
list(APPEND ADD_PRIVATE_INCLUDE "port/maixcam")
|
||||
endif()
|
||||
list(APPEND ADD_PRIVATE_INCLUDE "include_private")
|
||||
###############################################
|
||||
|
||||
############## Add source files ###############
|
||||
# list(APPEND ADD_SRCS "src/lib2.c"
|
||||
# )
|
||||
# FILE(GLOB_RECURSE EXTRA_SRC "src/*.c")
|
||||
# FILE(GLOB EXTRA_SRC "src/*.c")
|
||||
# list(APPEND ADD_SRCS ${EXTRA_SRC})
|
||||
# aux_source_directory(src ADD_SRCS) # collect all source file in src dir, will set var ADD_SRCS
|
||||
append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS
|
||||
if(PLATFORM_LINUX)
|
||||
append_srcs_dir(ADD_SRCS "port/linux")
|
||||
elseif(PLATFORM_MAIXCAM)
|
||||
append_srcs_dir(ADD_SRCS "port/maixcam")
|
||||
endif()
|
||||
# list(REMOVE_ITEM COMPONENT_SRCS "src/test.c")
|
||||
# set(ADD_ASM_SRCS "src/asm.S")
|
||||
# list(APPEND ADD_SRCS ${ADD_ASM_SRCS})
|
||||
# SET_PROPERTY(SOURCE ${ADD_ASM_SRCS} PROPERTY LANGUAGE C) # set .S ASM file as C language
|
||||
# SET_SOURCE_FILES_PROPERTIES(${ADD_ASM_SRCS} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp -D BBBBB")
|
||||
###############################################
|
||||
|
||||
|
||||
###### Add required/dependent components ######
|
||||
list(APPEND ADD_REQUIREMENTS basic opencv opencv_freetype websocket peripheral)
|
||||
list(APPEND ADD_REQUIREMENTS omv)
|
||||
list(APPEND ADD_REQUIREMENTS kvm_mmf)
|
||||
###############################################
|
||||
|
||||
###### Add link search path for requirements/libs ######
|
||||
# list(APPEND ADD_LINK_SEARCH_PATH "${CONFIG_TOOLCHAIN_PATH}/lib")
|
||||
# list(APPEND ADD_REQUIREMENTS pthread m) # add system libs, pthread and math lib for example here
|
||||
# set (OpenCV_DIR opencv/lib/cmake/opencv4)
|
||||
# find_package(OpenCV REQUIRED)
|
||||
###############################################
|
||||
|
||||
############ Add static libs ##################
|
||||
# list(APPEND ADD_STATIC_LIB "lib/libtest.a")
|
||||
###############################################
|
||||
|
||||
############ Add dynamic libs ##################
|
||||
# list(APPEND ADD_DYNAMIC_LIB "lib/arch/v831/libmaix_nn.so"
|
||||
# "lib/arch/v831/libmaix_cam.so"
|
||||
# )
|
||||
###############################################
|
||||
|
||||
#### Add compile option for this component ####
|
||||
#### Just for this component, won't affect other
|
||||
#### modules, including component that depend
|
||||
#### on this component
|
||||
# list(APPEND ADD_DEFINITIONS_PRIVATE -DAAAAA=1)
|
||||
|
||||
#### Add compile option for this component
|
||||
#### and components denpend on this component
|
||||
# list(APPEND ADD_DEFINITIONS -DAAAAA222=1
|
||||
# -DAAAAA333=1)
|
||||
###############################################
|
||||
|
||||
############ Add static libs ##################
|
||||
#### Update parent's variables like CMAKE_C_LINK_FLAGS
|
||||
# set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group libmaix/libtest.a -ltest2 -Wl,--end-group" PARENT_SCOPE)
|
||||
###############################################
|
||||
|
||||
# register component, DYNAMIC or SHARED flags will make component compiled to dynamic(shared) lib
|
||||
register_component()
|
||||
|
||||
0
support/sg2002/additional/vision/Kconfig
Normal file
0
support/sg2002/additional/vision/Kconfig
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @file maix_camera_base.hpp
|
||||
* @brief Maix camera SDL implementation
|
||||
* @author neucrack@sipeed.com
|
||||
* @license Apache 2.0 Sipeed Ltd
|
||||
* @update date 2023-10-23 Create by neucrack
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "maix_image.hpp"
|
||||
#include "maix_err.hpp"
|
||||
|
||||
namespace maix::camera
|
||||
{
|
||||
class CameraBase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Camera object
|
||||
* @param device camera device name, you can get devices by list_devices method, by default(value is NULL(None in MaixPy)) means the first device
|
||||
* @param width camera width, by default(value is -1) means auto detect,
|
||||
* if width > max device supported width, will auto set to max device supported width
|
||||
* @param height camera height, by default(value is -1) means auto detect,
|
||||
* if height > max device supported height, will auto set to max device supported height
|
||||
* @param format camera format, by default(value is FMT_RGB888)
|
||||
* @param buff_num camera buffer number, by default(value is 3)
|
||||
*/
|
||||
CameraBase(const char *device = nullptr, int width = -1, int height = -1, image::Format format = image::Format::FMT_RGB888, int buff_num = 3){};
|
||||
|
||||
/**
|
||||
* @brief Judge if the given format is supported by the camera
|
||||
*/
|
||||
virtual bool is_support_format(image::Format format) = 0;
|
||||
|
||||
/**
|
||||
* @brief open camera device
|
||||
* @param width camera width, by default(value is -1) means auto detect,
|
||||
* if width > max device supported width, will auto set to max device supported width
|
||||
* @param height camera height, by default(value is -1) means auto detect,
|
||||
* if height > max device supported height, will auto set to max device supported height
|
||||
* @param format camera format, by default(value is FMT_RGB888)
|
||||
* @param buff_num camera buffer number, by default(value is 3)
|
||||
* @return error code
|
||||
*/
|
||||
virtual err::Err open(int width = -1, int height = -1, image::Format format = image::Format::FMT_RGB888, int buff_num = 3) = 0;
|
||||
|
||||
/**
|
||||
* @brief read a frame from camera
|
||||
* @param buff buffer to store image data, if NULL, will alloc a new buffer
|
||||
* @return image data
|
||||
*/
|
||||
virtual image::Image *read(void *buff = NULL, size_t buff_size = 0) = 0;
|
||||
|
||||
/**
|
||||
* @brief close camera device
|
||||
* @return none
|
||||
*/
|
||||
virtual void close() = 0;
|
||||
|
||||
/**
|
||||
* Add a new channel and return a new Camera object, you can use close() to close this channel.
|
||||
* @param width camera width, default is -1, means auto, mostly means max width of camera support
|
||||
* @param height camera height, default is -1, means auto, mostly means max height of camera support
|
||||
* @param format camera output format, default is RGB888
|
||||
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
|
||||
* more than one buffer will accelerate image read speed, but will cost more memory.
|
||||
* @return new Camera object
|
||||
*/
|
||||
virtual camera::CameraBase *add_channel(int width = -1, int height = -1, image::Format format = image::FMT_RGB888, int buff_num = 3) = 0;
|
||||
|
||||
/**
|
||||
* @brief clear all buffer
|
||||
* @return none
|
||||
*/
|
||||
virtual void clear_buff() = 0;
|
||||
|
||||
/**
|
||||
* @brief check camera device is opened or not
|
||||
* @return opened or not, bool type
|
||||
*/
|
||||
virtual bool is_opened() = 0;
|
||||
|
||||
/**
|
||||
* Get camera supported channels(layers)
|
||||
*/
|
||||
virtual int get_ch_nums() = 0;
|
||||
|
||||
/**
|
||||
* Get channel number of camera.
|
||||
*/
|
||||
virtual int get_channel() = 0;
|
||||
|
||||
/**
|
||||
* Set/Get camera mirror
|
||||
* @param en enable/disable mirror
|
||||
*/
|
||||
virtual int hmirror(int en) = 0;
|
||||
|
||||
/**
|
||||
* Set/Get camera flip
|
||||
* @param en enable/disable flip
|
||||
*/
|
||||
virtual int vflip(int en) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
305
support/sg2002/additional/vision/include/maix_camera.hpp
Normal file
305
support/sg2002/additional/vision/include/maix_camera.hpp
Normal file
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
* @author neucrack@sipeed, lxowalle@sipeed
|
||||
* @copyright Sipeed Ltd 2023-
|
||||
* @license Apache 2.0
|
||||
* @update 2023.9.8: Add framework, create this file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "maix_tensor.hpp"
|
||||
#include "maix_log.hpp"
|
||||
#include "maix_image.hpp"
|
||||
#include "maix_err.hpp"
|
||||
#include "maix_camera_base.hpp"
|
||||
#include <stdlib.h>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
/**
|
||||
* @brief maix.camera module, access camera device and get image from it
|
||||
* @maixpy maix.camera
|
||||
*/
|
||||
namespace maix::camera
|
||||
{
|
||||
/**
|
||||
* List all supported camera devices.
|
||||
* @return Returns the path to the camera device.
|
||||
* @maixpy maix.camera.list_devices
|
||||
*/
|
||||
std::vector<std::string> list_devices();
|
||||
|
||||
/**
|
||||
* Enable set camera registers, default is false, if set to true, will not set camera registers, you can manually set registers by write_reg API.
|
||||
* @param enable enable/disable set camera registers
|
||||
* @maixpy maix.camera.set_regs_enable
|
||||
*/
|
||||
void set_regs_enable(bool enable = true);
|
||||
|
||||
/**
|
||||
* Camera class
|
||||
* @maixpy maix.camera.Camera
|
||||
*/
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Camera object.
|
||||
* Maximum resolution support 2560x1440.
|
||||
* @param width camera width, default is -1, means auto, mostly means max width of camera support
|
||||
* @param height camera height, default is -1, means auto, mostly means max height of camera support
|
||||
* @param format camera output format, default is image.Format.FMT_RGB888
|
||||
* @param device camera device path, you can get devices by list_devices method, by default(value is NULL(None in MaixPy)) means the first device
|
||||
* @param fps camera fps, default is -1, means auto, mostly means max fps of camera support
|
||||
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
|
||||
* more than one buffer will accelerate image read speed, but will cost more memory.
|
||||
* @param open If true, camera will automatically call open() after creation. default is true.
|
||||
* @maixpy maix.camera.Camera.__init__
|
||||
* @maixcdk maix.camera.Camera.Camera
|
||||
*/
|
||||
Camera(int width = -1, int height = -1, image::Format format = image::FMT_RGB888, const char *device = nullptr, int fps = -1, int buff_num = 3, bool open = true);
|
||||
|
||||
/**
|
||||
* @brief Construct a new Camera object.
|
||||
* @attention CameraBase * parameter need to be set manually, otherwise the operation of this object will be invalid.
|
||||
* @param device camera device path, you can get devices by list_devices method, by default(value is NULL(None in MaixPy)) means the first device
|
||||
* @param base basic operation objects.
|
||||
* @param width camera width, default is -1, means auto, mostly means max width of camera support
|
||||
* @param height camera height, default is -1, means auto, mostly means max height of camera support
|
||||
* @param format camera output format, default is image.Format.FMT_RGB888
|
||||
* @param fps camera fps, default is -1, means auto, mostly means max fps of camera support
|
||||
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
|
||||
* more than one buffer will accelerate image read speed, but will cost more memory.
|
||||
* @param open If true, camera will automatically call open() after creation. default is true.
|
||||
* @maixcdk maix.camera.Camera.Camera
|
||||
*/
|
||||
Camera(const char *device, CameraBase *base, int width = -1, int height = -1, image::Format format = image::FMT_RGB888, int fps = -1, int buff_num = -1, bool open = true);
|
||||
|
||||
~Camera();
|
||||
|
||||
void restart(int width = -1, int height = -1, image::Format format = image::FMT_RGB888, const char *device = nullptr, int fps = -1, int buff_num = 3, bool open = true);
|
||||
|
||||
/**
|
||||
* Get the number of channels supported by the camera.
|
||||
* @return Returns the maximum number of channels.
|
||||
* @maixpy maix.camera.Camera.get_ch_nums
|
||||
*/
|
||||
int get_ch_nums();
|
||||
|
||||
/**
|
||||
* Open camera and run
|
||||
* @param width camera width, default is -1, means auto, mostly means max width of camera support
|
||||
* @param height camera height, default is -1, means auto, mostly means max height of camera support
|
||||
* @param format camera output format, default same as the constructor's format argument
|
||||
* @param fps camera fps, default is -1, means auto, mostly means max fps of camera support
|
||||
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
|
||||
* more than one buffer will accelerate image read speed, but will cost more memory.
|
||||
* @return error code, err::ERR_NONE means success, others means failed
|
||||
* @maixpy maix.camera.Camera.open
|
||||
*/
|
||||
err::Err open(int width = -1, int height = -1, image::Format format = image::FMT_INVALID, int fps = -1, int buff_num = -1);
|
||||
|
||||
/**
|
||||
* Get one frame image from camera buffer, must call open method before read.
|
||||
* If open method not called, will call it automatically, if open failed, will throw exception!
|
||||
* So call open method before read is recommended.
|
||||
* @param buff buffer to store image data, if buff is nullptr, will alloc memory automatically.
|
||||
* In MaixPy, default to None, you can create a image.Image object, then pass img.data() to buff.
|
||||
* @param block block read, default is true, means block util read image successfully,
|
||||
* if set to false, will return nullptr if no image in buffer
|
||||
* @return image::Image object, if failed, return nullptr, you should delete if manually in C++
|
||||
* @maixpy maix.camera.Camera.read
|
||||
*/
|
||||
image::Image *read(void *buff = nullptr, size_t buff_size = 0, bool block = true);
|
||||
|
||||
/**
|
||||
* Clear buff to ensure the next read image is the latest image
|
||||
* @maixpy maix.camera.Camera.clear_buff
|
||||
*/
|
||||
void clear_buff();
|
||||
|
||||
/**
|
||||
* Read some frames and drop, this is usually used avoid read not stable image when camera just opened.
|
||||
* @param num number of frames to read and drop
|
||||
* @maixpy maix.camera.Camera.skip_frames
|
||||
*/
|
||||
void skip_frames(int num);
|
||||
|
||||
/**
|
||||
* Close camera
|
||||
* @maixpy maix.camera.Camera.close
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Add a new channel and return a new Camera object, you can use close() to close this channel.
|
||||
* @param width camera width, default is -1, means auto, mostly means max width of camera support
|
||||
* @param height camera height, default is -1, means auto, mostly means max height of camera support
|
||||
* @param format camera output format, default is RGB888
|
||||
* @param fps camera fps, default is -1, means auto, mostly means max fps of camera support
|
||||
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
|
||||
* more than one buffer will accelerate image read speed, but will cost more memory.
|
||||
* @param open If true, camera will automatically call open() after creation. default is true.
|
||||
* @return new Camera object
|
||||
* @maixpy maix.camera.Camera.add_channel
|
||||
*/
|
||||
camera::Camera *add_channel(int width = -1, int height = -1, image::Format format = image::FMT_RGB888, int fps = -1, int buff_num = 3, bool open = true);
|
||||
|
||||
/**
|
||||
* Check if camera is opened
|
||||
* @return true if camera is opened, false if not
|
||||
* @maixpy maix.camera.Camera.is_opened
|
||||
*/
|
||||
bool is_opened();
|
||||
|
||||
/**
|
||||
* @brief check camera device is closed or not
|
||||
* @return closed or not, bool type
|
||||
* @maixpy maix.camera.Camera.is_closed
|
||||
*/
|
||||
bool is_closed() { return !is_opened();}
|
||||
|
||||
/**
|
||||
* Get camera width
|
||||
* @return camera width
|
||||
* @maixpy maix.camera.Camera.width
|
||||
*/
|
||||
int width()
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get camera height
|
||||
* @return camera height
|
||||
* @maixpy maix.camera.Camera.height
|
||||
*/
|
||||
int height()
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get camera fps
|
||||
* @return camera fps
|
||||
* @maixpy maix.camera.Camera.fps
|
||||
*/
|
||||
int fps()
|
||||
{
|
||||
return _fps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get camera output format
|
||||
* @return camera output format, image::Format object
|
||||
* @maixpy maix.camera.Camera.format
|
||||
*/
|
||||
image::Format format()
|
||||
{
|
||||
return _format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get camera buffer number
|
||||
* @return camera buffer number
|
||||
* @maixpy maix.camera.Camera.buff_num
|
||||
*/
|
||||
int buff_num()
|
||||
{
|
||||
return _buff_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set/Get camera horizontal mirror
|
||||
* @return camera horizontal mirror
|
||||
* @maixpy maix.camera.Camera.hmirror
|
||||
*/
|
||||
int hmirror(int value = -1);
|
||||
|
||||
/**
|
||||
* Set/Get camera vertical flip
|
||||
* @return camera vertical flip
|
||||
* @maixpy maix.camera.Camera.vflip
|
||||
*/
|
||||
int vflip(int value = -1);
|
||||
|
||||
/**
|
||||
* Get camera device path
|
||||
* @return camera device path
|
||||
* @maixpy maix.camera.Camera.device
|
||||
*/
|
||||
std::string device()
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write camera register
|
||||
* @param addr register address
|
||||
* @param data register data
|
||||
* @param bit_width register data bit width, default is 8
|
||||
* @return error code, err::ERR_NONE means success, others means failed
|
||||
* @maixpy maix.camera.Camera.write_reg
|
||||
*/
|
||||
err::Err write_reg(int addr, int data, int bit_width = 8)
|
||||
{
|
||||
return err::ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read camera register
|
||||
* @param addr register address
|
||||
* @return register data, -1 means failed
|
||||
* @param bit_width register data bit width, default is 8
|
||||
* @maixpy maix.camera.Camera.read_reg
|
||||
*/
|
||||
int read_reg(int addr, int bit_width = 8)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Camera output color bar image for test
|
||||
* @param enable enable/disable color bar
|
||||
* @return error code, err::ERR_NONE means success, others means failed
|
||||
* @maixpy maix.camera.Camera.show_colorbar
|
||||
*/
|
||||
err::Err show_colorbar(bool enable);
|
||||
|
||||
/**
|
||||
* Get channel of camera
|
||||
* @return channel number
|
||||
* @maixpy maix.camera.Camera.get_channel
|
||||
*/
|
||||
int get_channel();
|
||||
|
||||
/**
|
||||
* Set camera resolution
|
||||
* @param width new width
|
||||
* @param height new height
|
||||
* @return error code, err::ERR_NONE means success, others means failed
|
||||
* @maixpy maix.camera.Camera.set_resolution
|
||||
*/
|
||||
err::Err set_resolution(int width, int height);
|
||||
|
||||
private:
|
||||
std::string _device;
|
||||
int _ch;
|
||||
int _width;
|
||||
int _height;
|
||||
int _fps;
|
||||
int _buff_num;
|
||||
image::Format _format;
|
||||
image::Format _format_impl; // used by implement code and need convert to _format
|
||||
int _hmirror;
|
||||
int _vflip;
|
||||
float _exposure;
|
||||
float _gain;
|
||||
bool _show_colorbar;
|
||||
bool _open_set_regs;
|
||||
CameraBase *_impl; // used by implement code
|
||||
bool _check_format(image::Format format);
|
||||
};
|
||||
}
|
||||
1540
support/sg2002/additional/vision/include/maix_image.hpp
Normal file
1540
support/sg2002/additional/vision/include/maix_image.hpp
Normal file
File diff suppressed because it is too large
Load Diff
296
support/sg2002/additional/vision/include/maix_image_color.hpp
Normal file
296
support/sg2002/additional/vision/include/maix_image_color.hpp
Normal file
@@ -0,0 +1,296 @@
|
||||
/**
|
||||
* @author neucrack@sipeed, lxowalle@sipeed
|
||||
* @copyright Sipeed Ltd 2023-
|
||||
* @license Apache 2.0
|
||||
* @update 2023.9.8: Add framework, create this file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "maix_image_def.hpp"
|
||||
#include "maix_log.hpp"
|
||||
|
||||
namespace maix::image
|
||||
{
|
||||
/**
|
||||
* Color class
|
||||
* @maixpy maix.image.Color
|
||||
*/
|
||||
class Color
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Color constructor
|
||||
* @param alpha alpha channel, value range: 0 ~ 1
|
||||
* @maixpy maix.image.Color.__init__
|
||||
*/
|
||||
Color(uint8_t ch1, uint8_t ch2 = 0, uint8_t ch3 = 0, float alpha = 0, image::Format format = image::FMT_GRAYSCALE)
|
||||
{
|
||||
if(alpha > 1 || alpha < 0)
|
||||
throw std::runtime_error("alpha value range: 0 ~ 1");
|
||||
this->format = format;
|
||||
switch (format)
|
||||
{
|
||||
case image::FMT_RGB888:
|
||||
r = ch1;
|
||||
g = ch2;
|
||||
b = ch3;
|
||||
this->alpha = 1;
|
||||
break;
|
||||
case image::FMT_BGR888:
|
||||
b = ch1;
|
||||
g = ch2;
|
||||
r = ch3;
|
||||
this->alpha = 1;
|
||||
break;
|
||||
case image::FMT_GRAYSCALE:
|
||||
gray = ch1;
|
||||
break;
|
||||
case image::FMT_BGRA8888:
|
||||
b = ch1;
|
||||
g = ch2;
|
||||
r = ch3;
|
||||
this->alpha = alpha;
|
||||
break;
|
||||
case image::FMT_RGBA8888:
|
||||
r = ch1;
|
||||
g = ch2;
|
||||
b = ch3;
|
||||
this->alpha = alpha;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("not support format");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Color red channel
|
||||
* @maixpy maix.image.Color.r
|
||||
*/
|
||||
uint8_t r;
|
||||
|
||||
/**
|
||||
* Color green channel
|
||||
* @maixpy maix.image.Color.g
|
||||
*/
|
||||
uint8_t g;
|
||||
|
||||
/**
|
||||
* Color blue channel
|
||||
* @maixpy maix.image.Color.b
|
||||
*/
|
||||
uint8_t b;
|
||||
|
||||
/**
|
||||
* Color alpha channel, value from 0.0 to 1.0, float value
|
||||
* @maixpy maix.image.Color.alpha
|
||||
*/
|
||||
float alpha;
|
||||
|
||||
/**
|
||||
* Color gray channel
|
||||
* @maixpy maix.image.Color.gray
|
||||
*/
|
||||
uint8_t gray;
|
||||
|
||||
/**
|
||||
* Color format
|
||||
* @maixpy maix.image.Color.format
|
||||
*/
|
||||
image::Format format;
|
||||
|
||||
/**
|
||||
* Get color's hex value
|
||||
* @maixpy maix.image.Color.hex
|
||||
*/
|
||||
uint32_t hex()
|
||||
{
|
||||
uint32_t hex = 0;
|
||||
switch (format)
|
||||
{
|
||||
case image::FMT_RGB888:
|
||||
hex = r | (g << 8) | (b << 16);
|
||||
break;
|
||||
case image::FMT_BGR888:
|
||||
hex = b | (g << 8) | (r << 16);
|
||||
break;
|
||||
case image::FMT_GRAYSCALE:
|
||||
hex = gray;
|
||||
break;
|
||||
case image::FMT_BGRA8888:
|
||||
hex = b | (g << 8) | (r << 16) | ((uint8_t)(alpha*255) << 24);
|
||||
break;
|
||||
case image::FMT_RGBA8888:
|
||||
hex = r | (g << 8) | (b << 16) | ((uint8_t)(alpha*255) << 24);
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("not support format");
|
||||
break;
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Color object from RGB channels
|
||||
* @maixpy maix.image.Color.from_rgb
|
||||
*/
|
||||
static image::Color from_rgb(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
return Color(r, g, b, 1, image::Format::FMT_RGB888);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Color object from BGR channels
|
||||
* @maixpy maix.image.Color.from_bgr
|
||||
*/
|
||||
static image::Color from_bgr(uint8_t b, uint8_t g, uint8_t r)
|
||||
{
|
||||
return Color(b, g, r, 1, image::Format::FMT_BGR888);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Color object from gray channel
|
||||
* @maixpy maix.image.Color.from_gray
|
||||
*/
|
||||
static image::Color from_gray(uint8_t gray)
|
||||
{
|
||||
return Color(gray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Color object from RGBA channels
|
||||
* @param alpha alpha channel, float value, value range: 0 ~ 1
|
||||
* @maixpy maix.image.Color.from_rgba
|
||||
*/
|
||||
static image::Color from_rgba(uint8_t r, uint8_t g, uint8_t b, float alpha)
|
||||
{
|
||||
return Color(r, g, b, alpha, image::Format::FMT_RGBA8888);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Color object from BGRA channels
|
||||
* * @param alpha alpha channel, float value, value range: 0 ~ 1
|
||||
* @maixpy maix.image.Color.from_bgra
|
||||
*/
|
||||
static image::Color from_bgra(uint8_t b, uint8_t g, uint8_t r, float alpha)
|
||||
{
|
||||
return Color(b, g, r, alpha, image::Format::FMT_BGRA8888);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Color object from hex value
|
||||
* @param hex hex value, e.g. 0x0000FF00, lower address if first channel
|
||||
* @param format color format, @see image::Format
|
||||
* @maixpy maix.image.Color.from_hex
|
||||
*/
|
||||
static image::Color from_hex(uint32_t hex, image::Format &format)
|
||||
{
|
||||
return Color(hex & 0xFF, hex & 0xFF00, hex & 0xFF0000, (hex & 0xFF000000)/255.0, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Color format
|
||||
* @param format format want to convert to, @see image::Format, only support RGB888, BGR888, RGBA8888, BGRA8888, GRAYSCALE.
|
||||
* @maixpy maix.image.Color.to_format
|
||||
*/
|
||||
void to_format(const image::Format &format)
|
||||
{
|
||||
if(!(format == image::FMT_RGB888 || format == image::FMT_BGR888 ||
|
||||
format == image::FMT_RGBA8888 || format == image::FMT_BGRA8888 ||
|
||||
format == image::FMT_GRAYSCALE))
|
||||
{
|
||||
log::error("convert format failed, not support format %d\n", format);
|
||||
return;
|
||||
}
|
||||
if(this->format == format)
|
||||
return;
|
||||
if((this->format == image::FMT_RGB888 || this->format == image::FMT_BGR888) &&
|
||||
(format == image::FMT_RGBA8888 || format == image::FMT_BGRA8888))
|
||||
{
|
||||
this->alpha = 1;
|
||||
}
|
||||
else if(this->format == image::FMT_GRAYSCALE && format != image::FMT_GRAYSCALE)
|
||||
{
|
||||
this->r = this->gray;
|
||||
this->g = this->gray;
|
||||
this->b = this->gray;
|
||||
this->alpha = 1;
|
||||
}
|
||||
else if((this->format == image::FMT_RGBA8888 || this->format == image::FMT_BGRA8888) &&
|
||||
(format == image::FMT_RGB888 || format == image::FMT_BGR888))
|
||||
{
|
||||
this->alpha = 0;
|
||||
}
|
||||
else if(this->format != image::FMT_GRAYSCALE && format == image::FMT_GRAYSCALE)
|
||||
{
|
||||
this->gray = (this->r + this->g + this->b) / 3;
|
||||
this->r = this->gray;
|
||||
this->g = this->gray;
|
||||
this->b = this->gray;
|
||||
this->alpha = 0;
|
||||
}
|
||||
this->format = format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert color format and return a new Color object
|
||||
* @param format format want to convert to, @see image::Format, only support RGB888, BGR888, RGBA8888, BGRA8888, GRAYSCALE.
|
||||
* @return new Color object, you need to delete it manually in C++.
|
||||
* @maixpy maix.image.Color.to_format2
|
||||
*/
|
||||
image::Color *to_format2(const image::Format &format)
|
||||
{
|
||||
image::Color *color = new image::Color(*this);
|
||||
color->to_format(format);
|
||||
return color;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Predefined color white
|
||||
* @maixpy maix.image.COLOR_WHITE
|
||||
*/
|
||||
const image::Color COLOR_WHITE = image::Color::from_rgb(255, 255, 255);
|
||||
/**
|
||||
* Predefined color black
|
||||
* @maixpy maix.image.COLOR_BLACK
|
||||
*/
|
||||
const image::Color COLOR_BLACK = image::Color::from_rgb(0, 0, 0);
|
||||
/**
|
||||
* Predefined color red
|
||||
* @maixpy maix.image.COLOR_RED
|
||||
*/
|
||||
const image::Color COLOR_RED = image::Color::from_rgb(255, 0, 0);
|
||||
/**
|
||||
* Predefined color green
|
||||
* @maixpy maix.image.COLOR_GREEN
|
||||
*/
|
||||
const image::Color COLOR_GREEN = image::Color::from_rgb(0, 255, 0);
|
||||
/**
|
||||
* Predefined color blue
|
||||
* @maixpy maix.image.COLOR_BLUE
|
||||
*/
|
||||
const image::Color COLOR_BLUE = image::Color::from_rgb(0, 0, 255);
|
||||
/**
|
||||
* Predefined color yellow
|
||||
* @maixpy maix.image.COLOR_YELLOW
|
||||
*/
|
||||
const image::Color COLOR_YELLOW = image::Color::from_rgb(255, 255, 0);
|
||||
/**
|
||||
* Predefined color purple
|
||||
* @maixpy maix.image.COLOR_PURPLE
|
||||
*/
|
||||
const image::Color COLOR_PURPLE = image::Color::from_rgb(143, 0, 255);
|
||||
/**
|
||||
* Predefined color orange
|
||||
* @maixpy maix.image.COLOR_ORANGE
|
||||
*/
|
||||
const image::Color COLOR_ORANGE = image::Color::from_rgb(255, 127, 0);
|
||||
/**
|
||||
* Predefined color gray
|
||||
* @maixpy maix.image.COLOR_GRAY
|
||||
*/
|
||||
const image::Color COLOR_GRAY = image::Color::from_rgb(127, 127, 127);
|
||||
|
||||
}
|
||||
313
support/sg2002/additional/vision/include/maix_image_def.hpp
Normal file
313
support/sg2002/additional/vision/include/maix_image_def.hpp
Normal file
@@ -0,0 +1,313 @@
|
||||
/**
|
||||
* @author neucrack@sipeed, lxowalle@sipeed
|
||||
* @copyright Sipeed Ltd 2023-
|
||||
* @license Apache 2.0
|
||||
* @update 2023.9.8: Add framework, create this file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace maix::image
|
||||
{
|
||||
|
||||
/**
|
||||
* Image formats
|
||||
* @attention for MaixPy firmware developers, update this enum will also need to update the fmt_size and fmt_names too !!!
|
||||
* @maixpy maix.image.Format
|
||||
*/
|
||||
enum Format
|
||||
{
|
||||
FMT_RGB888 = 0, // RGBRGB...RGB, R at the lowest address
|
||||
FMT_BGR888, // BGRBGR...BGR, B at the lowest address
|
||||
FMT_RGBA8888, // RGBARGBA...RGBA, R at the lowest address
|
||||
FMT_BGRA8888, // BGRABGRA...BGRA, B at the lowest address
|
||||
FMT_RGB565,
|
||||
FMT_BGR565,
|
||||
FMT_YUV422SP, // YYY...UVUVUV...UVUV
|
||||
FMT_YUV422P, // YYY...UUU...VVV
|
||||
FMT_YVU420SP, // YYY...VUVUVU...VUVU, NV21
|
||||
FMT_YUV420SP, // YYY...UVUVUV...UVUV, NV12
|
||||
FMT_YVU420P, // YYY...VVV...UUU
|
||||
FMT_YUV420P, // YYY...UUU...VVV
|
||||
FMT_GRAYSCALE,
|
||||
FMT_BGGR6, // 6-bit Bayer format with a BGGR pattern.
|
||||
FMT_GBRG6, // 6-bit Bayer format with a GBRG pattern.
|
||||
FMT_GRBG6, // 6-bit Bayer format with a GRBG pattern.
|
||||
FMT_RGGB6, // 6-bit Bayer format with a RGGB pattern.
|
||||
FMT_BGGR8, // 8-bit Bayer format with a BGGR pattern.
|
||||
FMT_GBRG8, // 8-bit Bayer format with a GBRG pattern.
|
||||
FMT_GRBG8, // 8-bit Bayer format with a GRBG pattern.
|
||||
FMT_RGGB8, // 8-bit Bayer format with a RGGB pattern.
|
||||
FMT_BGGR10, // 10-bit Bayer format with a BGGR pattern.
|
||||
FMT_GBRG10, // 10-bit Bayer format with a GBRG pattern.
|
||||
FMT_GRBG10, // 10-bit Bayer format with a GRBG pattern.
|
||||
FMT_RGGB10, // 10-bit Bayer format with a RGGB pattern.
|
||||
FMT_BGGR12, // 12-bit Bayer format with a BGGR pattern.
|
||||
FMT_GBRG12, // 12-bit Bayer format with a GBRG pattern.
|
||||
FMT_GRBG12, // 12-bit Bayer format with a GRBG pattern.
|
||||
FMT_RGGB12, // 12-bit Bayer format with a RGGB pattern.
|
||||
FMT_UNCOMPRESSED_MAX,
|
||||
|
||||
// compressed format below, not compressed should define upper
|
||||
FMT_COMPRESSED_MIN,
|
||||
FMT_JPEG,
|
||||
FMT_PNG,
|
||||
FMT_COMPRESSED_MAX,
|
||||
|
||||
FMT_INVALID = 0xFF // format not valid
|
||||
}; // !!!! update this section please update fmt_size and fmt_names too !!!!
|
||||
|
||||
/**
|
||||
* Image format size in bytes
|
||||
* @attention It's a copy of this variable in MaixPy,
|
||||
* so change it in C++ (e.g. update var in hello function) will not take effect the var inMaixPy.
|
||||
* So we add const for this var to avoid this mistake.
|
||||
* @maixpy maix.image.fmt_size
|
||||
*/
|
||||
const std::vector<float> fmt_size = {
|
||||
3,
|
||||
3,
|
||||
4,
|
||||
4,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
1.5,
|
||||
1.5,
|
||||
1.5,
|
||||
1.5,
|
||||
1, // grayscale
|
||||
0.75, // 6-bit Bayer format
|
||||
0.75, // 6-bit Bayer format
|
||||
0.75, // 6-bit Bayer format
|
||||
0.75, // 6-bit Bayer format
|
||||
1, // 8-bit Bayer format
|
||||
1, // 8-bit Bayer format
|
||||
1, // 8-bit Bayer format
|
||||
1, // 8-bit Bayer format
|
||||
1.25, // 10-bit Bayer format
|
||||
1.25, // 10-bit Bayer format
|
||||
1.25, // 10-bit Bayer format
|
||||
1.25, // 10-bit Bayer format
|
||||
1.5, // 12-bit Bayer format
|
||||
1.5, // 12-bit Bayer format
|
||||
1.5, // 12-bit Bayer format
|
||||
1.5, // 12-bit Bayer format
|
||||
0, // uncompereed_max
|
||||
0, // compressed_min
|
||||
1, // jpeg
|
||||
1, // png
|
||||
0, // compressed_max
|
||||
0 // invalid
|
||||
};
|
||||
|
||||
/**
|
||||
* Image format string
|
||||
* @maixpy maix.image.fmt_names
|
||||
*/
|
||||
const std::vector<std::string> fmt_names = {
|
||||
"RGB888",
|
||||
"BGR888",
|
||||
"RGBA8888",
|
||||
"BGRA8888",
|
||||
"RGB565",
|
||||
"BGR565",
|
||||
"YUV422SP",
|
||||
"YUV422P",
|
||||
"YVU420SP",
|
||||
"YUV420SP",
|
||||
"YVU420P",
|
||||
"YUV420P",
|
||||
"GRAYSCALE",
|
||||
"BGGR6",
|
||||
"GBRG6",
|
||||
"GRBG6",
|
||||
"RG6B6",
|
||||
"BGGR8",
|
||||
"GBRG8",
|
||||
"GRBG8",
|
||||
"RG6B8",
|
||||
"BGGR10",
|
||||
"GBRG10",
|
||||
"GRBG10",
|
||||
"RG6B10",
|
||||
"BGGR12",
|
||||
"GBRG12",
|
||||
"GRBG12",
|
||||
"RG6B12",
|
||||
"UNCOMPRESSED_MAX",
|
||||
"COMPRESSED_MIN",
|
||||
"JPEG",
|
||||
"PNG",
|
||||
"COMPRESSED_MAX",
|
||||
"INVALID"
|
||||
};
|
||||
|
||||
/**
|
||||
* Image size type
|
||||
* @maixpy maix.image.Size
|
||||
*/
|
||||
class Size
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a new Size object
|
||||
* @param width image width
|
||||
* @param height image height
|
||||
* @maixpy maix.image.Size.__init__
|
||||
*/
|
||||
Size(int width = 0, int height = 0)
|
||||
{
|
||||
this->_width = width;
|
||||
this->_height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* width of size
|
||||
* @param width set new width, if not set, only return current width
|
||||
* @maixpy maix.image.Size.width
|
||||
*/
|
||||
int width(int width = -1)
|
||||
{
|
||||
if(width != -1)
|
||||
{
|
||||
this->_width = width;
|
||||
}
|
||||
return this->_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* height of size
|
||||
* @param height set new height, if not set, only return current height
|
||||
* @maixpy maix.image.Size.height
|
||||
*/
|
||||
int height(int height = -1)
|
||||
{
|
||||
if(height != -1)
|
||||
{
|
||||
this->_height = height;
|
||||
}
|
||||
return this->_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscript operator
|
||||
* @param index 0 for width, 1 for height
|
||||
* @return int& width or height
|
||||
* @maixpy maix.image.Size.__getitem__
|
||||
* @maixcdk maix.image.Size.operator[]
|
||||
*/
|
||||
int &operator[](int index)
|
||||
{
|
||||
if (index == 0)
|
||||
return _width;
|
||||
else if (index == 1)
|
||||
return _height;
|
||||
else
|
||||
throw std::out_of_range("Size index out of range");
|
||||
}
|
||||
|
||||
/**
|
||||
* to string
|
||||
* @maixpy maix.image.Size.__str__
|
||||
*/
|
||||
std::string __str__()
|
||||
{
|
||||
return "Size(" + std::to_string(_width) + "x" + std::to_string(_height) + ")";
|
||||
}
|
||||
private:
|
||||
int _width;
|
||||
int _height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Object fit method
|
||||
* @maixpy maix.image.Fit
|
||||
*/
|
||||
enum Fit
|
||||
{
|
||||
FIT_NONE = -1, // no object fit, keep original
|
||||
FIT_FILL = 0, // width to new width, height to new height, may be stretch
|
||||
FIT_CONTAIN, // keep aspect ratio, fill blank area with black color
|
||||
FIT_COVER, // keep aspect ratio, crop image to fit new size
|
||||
FIT_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* Resize method
|
||||
* @maixpy maix.image.ResizeMethod
|
||||
*/
|
||||
enum ResizeMethod
|
||||
{
|
||||
NEAREST = 0,
|
||||
BILINEAR,
|
||||
BICUBIC,
|
||||
AREA,
|
||||
LANCZOS,
|
||||
HAMMING,
|
||||
RESIZE_METHOD_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* Family of apriltag
|
||||
* @maixpy maix.image.ApriltagFamilies
|
||||
*/
|
||||
enum ApriltagFamilies
|
||||
{
|
||||
TAG16H5 = 1,
|
||||
TAG25H7 = 2,
|
||||
TAG25H9 = 4,
|
||||
TAG36H10 = 8,
|
||||
TAG36H11 = 16,
|
||||
ARTOOLKIT = 32
|
||||
};
|
||||
|
||||
/**
|
||||
* Template match method
|
||||
* @maixpy maix.image.TemplateMatch
|
||||
*/
|
||||
enum TemplateMatch
|
||||
{
|
||||
SEARCH_EX, // Exhaustive search
|
||||
SEARCH_DS, // Diamond search
|
||||
};
|
||||
|
||||
/**
|
||||
* CornerDetector class
|
||||
* @maixpy maix.image.CornerDetector
|
||||
*/
|
||||
enum CornerDetector
|
||||
{
|
||||
CORNER_FAST,
|
||||
CORNER_AGAST
|
||||
};
|
||||
|
||||
/**
|
||||
* EdgeDetector class
|
||||
* @maixpy maix.image.EdgeDetector
|
||||
*/
|
||||
enum EdgeDetector
|
||||
{
|
||||
EDGE_CANNY,
|
||||
EDGE_SIMPLE,
|
||||
};
|
||||
|
||||
/**
|
||||
* FlipDir
|
||||
* @maixpy maix.image.FlipDir
|
||||
*/
|
||||
enum class FlipDir
|
||||
{
|
||||
X,
|
||||
Y,
|
||||
XY
|
||||
};
|
||||
|
||||
}
|
||||
2543
support/sg2002/additional/vision/include/maix_image_obj.hpp
Normal file
2543
support/sg2002/additional/vision/include/maix_image_obj.hpp
Normal file
File diff suppressed because it is too large
Load Diff
4
support/sg2002/additional/vision/include/maix_vision.hpp
Normal file
4
support/sg2002/additional/vision/include/maix_vision.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "maix_image.hpp"
|
||||
#include "maix_display.hpp"
|
||||
#include "maix_camera.hpp"
|
||||
#include "maix_video.hpp"
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "maix_image.hpp"
|
||||
#include "omv.hpp"
|
||||
|
||||
namespace maix::image
|
||||
{
|
||||
/**
|
||||
* Convert image to openmv image format
|
||||
* @param image image
|
||||
* @param imlib_image openmv image
|
||||
* @return
|
||||
*/
|
||||
extern void convert_to_imlib_image(image::Image *image, image_t *imlib_image);
|
||||
extern void _convert_to_lab_thresholds(std::vector<std::vector<int>> &in, list_t *out);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* @author lxowalle@sipeed
|
||||
* @copyright Sipeed Ltd 2023-
|
||||
* @license Apache 2.0
|
||||
* @update 2023.9.8: Add framework, create this file.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "maix_err.hpp"
|
||||
#include "maix_basic.hpp"
|
||||
#include "maix_log.hpp"
|
||||
#include "maix_image.hpp"
|
||||
#include "maix_time.hpp"
|
||||
#include "maix_camera_base.hpp"
|
||||
#include "kvm_mmf.hpp"
|
||||
#include <signal.h>
|
||||
|
||||
static void try_deinit_mmf()
|
||||
{
|
||||
static uint8_t is_called = 0;
|
||||
if (!is_called) {
|
||||
mmf_try_deinit(true);
|
||||
is_called = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void signal_handle(int signal)
|
||||
{
|
||||
const char *signal_msg = NULL;
|
||||
switch (signal) {
|
||||
case SIGILL: signal_msg = "SIGILL"; break;
|
||||
case SIGTRAP: signal_msg = "SIGTRAP"; break;
|
||||
case SIGABRT: signal_msg = "SIGABRT"; break;
|
||||
case SIGBUS: signal_msg = "SIGBUS"; break;
|
||||
case SIGFPE: signal_msg = "SIGFPE"; break;
|
||||
case SIGKILL: signal_msg = "SIGKILL"; break;
|
||||
case SIGSEGV: signal_msg = "SIGSEGV"; break;
|
||||
default: signal_msg = "UNKNOWN"; break;
|
||||
}
|
||||
|
||||
maix::log::error("Trigger signal, code:%s(%d)!\r\n", signal_msg, signal);
|
||||
try_deinit_mmf();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// FIXME: move this function to port/maix_vision_maixcam.cpp ?
|
||||
static __attribute__((constructor)) void maix_vision_register_signal(void)
|
||||
{
|
||||
signal(SIGILL, signal_handle);
|
||||
signal(SIGTRAP, signal_handle);
|
||||
signal(SIGABRT, signal_handle);
|
||||
signal(SIGBUS, signal_handle);
|
||||
signal(SIGFPE, signal_handle);
|
||||
signal(SIGKILL, signal_handle);
|
||||
signal(SIGSEGV, signal_handle);
|
||||
|
||||
maix::util::register_exit_function(try_deinit_mmf);
|
||||
}
|
||||
|
||||
namespace maix::camera
|
||||
{
|
||||
class CameraCviMmf final : public CameraBase
|
||||
{
|
||||
public:
|
||||
CameraCviMmf(const std::string device, int width, int height, image::Format format, int buff_num)
|
||||
{
|
||||
this->device = device;
|
||||
this->format = format;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->buffer_num = buff_num;
|
||||
this->ch = -1;
|
||||
|
||||
if (0 != mmf_init()) {
|
||||
err::check_raise(err::ERR_RUNTIME, "mmf init failed");
|
||||
}
|
||||
|
||||
if (0 != mmf_vi_init()) {
|
||||
err::check_raise(err::ERR_RUNTIME, "mmf vi init failed");
|
||||
}
|
||||
}
|
||||
|
||||
CameraCviMmf(const std::string device, int ch, int width, int height, image::Format format, int buff_num)
|
||||
{
|
||||
this->device = device;
|
||||
this->format = format;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->buffer_num = buff_num;
|
||||
this->ch = ch;
|
||||
|
||||
if (0 != mmf_init()) {
|
||||
err::check_raise(err::ERR_RUNTIME, "mmf init failed");
|
||||
}
|
||||
|
||||
if (0 != mmf_vi_init()) {
|
||||
err::check_raise(err::ERR_RUNTIME, "mmf vi init failed");
|
||||
}
|
||||
}
|
||||
|
||||
~CameraCviMmf()
|
||||
{
|
||||
mmf_del_vi_channel(this->ch);
|
||||
if (0 != mmf_vi_deinit()) {
|
||||
err::check_raise(err::ERR_RUNTIME, "mmf vi init failed");
|
||||
}
|
||||
mmf_try_deinit(true);
|
||||
}
|
||||
|
||||
err::Err open(int width, int height, image::Format format, int buff_num)
|
||||
{
|
||||
if (format == image::FMT_GRAYSCALE) {
|
||||
format = image::FMT_YVU420SP;
|
||||
}
|
||||
int ch = mmf_get_vi_unused_channel();
|
||||
if (ch < 0) {
|
||||
log::error("camera open: mmf get vi channel failed");
|
||||
return err::ERR_RUNTIME;
|
||||
}
|
||||
if (0 != mmf_add_vi_channel(ch, width, height, mmf_invert_format_to_mmf(format))) {
|
||||
log::error("camera open: mmf add vi channel failed");
|
||||
return err::ERR_RUNTIME;
|
||||
}
|
||||
|
||||
this->ch = ch;
|
||||
this->width = (width == -1) ? this->width : width;
|
||||
this->height = (height == -1) ? this->height : height;
|
||||
this->align_width = mmf_vi_aligned_width(this->ch);
|
||||
this->align_need = (this->width % this->align_width == 0) ? false : true; // Width need align only
|
||||
return err::ERR_NONE;
|
||||
} // open
|
||||
|
||||
bool is_support_format(image::Format format)
|
||||
{
|
||||
if(format == image::Format::FMT_RGB888 || format == image::Format::FMT_BGR888
|
||||
|| format == image::Format::FMT_YVU420SP|| format == image::Format::FMT_GRAYSCALE)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (mmf_vi_chn_is_open(this->ch) == true) {
|
||||
if (0 != mmf_del_vi_channel(this->ch)) {
|
||||
log::error("mmf del vi channel failed");
|
||||
}
|
||||
}
|
||||
} // close
|
||||
|
||||
// read
|
||||
image::Image *read(void *buff = NULL, size_t buff_size = 0)
|
||||
{
|
||||
// printf("Func: maix_image.cpp read\r\n");
|
||||
image::Image *img = NULL;
|
||||
|
||||
void *buffer = NULL;
|
||||
int buffer_len = 0, width = 0, height = 0, format = 0;
|
||||
|
||||
if (0 == mmf_vi_frame_pop(this->ch, &buffer, &buffer_len, &width, &height, &format)) {
|
||||
if (buffer == NULL) {
|
||||
mmf_vi_frame_free(this->ch);
|
||||
printf("mmf_vi_frame_free error\r\n");
|
||||
return NULL;
|
||||
}
|
||||
if(buff)
|
||||
{
|
||||
if(buff_size < (size_t)buffer_len)
|
||||
{
|
||||
log::error("camera read: buff size not enough, need %d, but %d", buffer_len, buff_size);
|
||||
mmf_vi_frame_free(this->ch);
|
||||
return NULL;
|
||||
}
|
||||
img = new image::Image(width, height, this->format, (uint8_t*)buff, buff_size, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
img = new image::Image(this->width, this->height, this->format);
|
||||
}
|
||||
void *image_data = img->data();
|
||||
switch (img->format()) {
|
||||
case image::Format::FMT_GRAYSCALE:
|
||||
if (this->align_need) {
|
||||
for (int h = 0; h < this->height; h ++) {
|
||||
memcpy((uint8_t *)image_data + h * this->width, (uint8_t *)buffer + h * width, this->width);
|
||||
}
|
||||
} else {
|
||||
memcpy(image_data, buffer, this->width * this->height);
|
||||
}
|
||||
break;
|
||||
case image::Format::FMT_BGR888: // fall through
|
||||
case image::Format::FMT_RGB888:
|
||||
if (this->align_need) {
|
||||
for (int h = 0; h < this->height; h++) {
|
||||
memcpy((uint8_t *)image_data + h * this->width * 3, (uint8_t *)buffer + h * width * 3, this->width * 3);
|
||||
}
|
||||
} else {
|
||||
memcpy(image_data, buffer, this->width * this->height * 3);
|
||||
}
|
||||
break;
|
||||
case image::Format::FMT_YVU420SP:
|
||||
if (this->align_need) {
|
||||
for (int h = 0; h < this->height * 3 / 2; h ++) {
|
||||
memcpy((uint8_t *)image_data + h * this->width, (uint8_t *)buffer + h * width, this->width);
|
||||
}
|
||||
} else {
|
||||
memcpy(image_data, buffer, this->width * this->height * 3 / 2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("unknown format\n");
|
||||
delete img;
|
||||
mmf_vi_frame_free(this->ch);
|
||||
printf("switch (img->format()\r\n");
|
||||
return NULL;
|
||||
}
|
||||
mmf_vi_frame_free(this->ch);
|
||||
// printf("mmf_vi_frame_free\r\n");
|
||||
return img;
|
||||
}
|
||||
|
||||
return img;
|
||||
} // read
|
||||
|
||||
camera::CameraCviMmf *add_channel(int width, int height, image::Format format, int buff_num)
|
||||
{
|
||||
int new_channel = mmf_get_vi_unused_channel();
|
||||
if (new_channel < 0) {
|
||||
log::error("Support not more channel!\r\n");
|
||||
return NULL;
|
||||
}
|
||||
return new camera::CameraCviMmf(this->device, new_channel, width, height, format, buff_num);
|
||||
}
|
||||
|
||||
void clear_buff()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool is_opened() {
|
||||
return mmf_vi_chn_is_open(this->ch);
|
||||
}
|
||||
|
||||
int get_ch_nums() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_channel() {
|
||||
return this->ch;
|
||||
}
|
||||
|
||||
int hmirror(int en)
|
||||
{
|
||||
bool out;
|
||||
if (en == -1) {
|
||||
mmf_get_vi_hmirror(this->ch, &out);
|
||||
} else {
|
||||
bool need_open = false;
|
||||
if (this->is_opened()) {
|
||||
this->close();
|
||||
need_open = true;
|
||||
}
|
||||
|
||||
mmf_set_vi_hmirror(this->ch, en);
|
||||
|
||||
if (need_open) {
|
||||
err::check_raise(this->open(this->width, this->height, this->format, this->buffer_num), "Open failed");
|
||||
}
|
||||
out = en;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int vflip(int en)
|
||||
{
|
||||
bool out;
|
||||
if (en == -1) {
|
||||
mmf_get_vi_vflip(this->ch, &out);
|
||||
} else {
|
||||
bool need_open = false;
|
||||
if (this->is_opened()) {
|
||||
this->close();
|
||||
need_open = true;
|
||||
}
|
||||
|
||||
mmf_set_vi_vflip(this->ch, en);
|
||||
|
||||
if (need_open) {
|
||||
err::check_raise(this->open(this->width, this->height, this->format, this->buffer_num), "Open failed");
|
||||
}
|
||||
out = en;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string device;
|
||||
image::Format format;
|
||||
int fd;
|
||||
int ch;
|
||||
uint32_t raw_format;
|
||||
std::vector<void*> buffers;
|
||||
std::vector<int> buffers_len;
|
||||
int buffer_num;
|
||||
int queue_id; // user directly used buffer id
|
||||
int width;
|
||||
int height;
|
||||
void *buff;
|
||||
bool buff_alloc;
|
||||
int align_width;
|
||||
bool align_need;
|
||||
};
|
||||
|
||||
} // namespace maix::camera
|
||||
425
support/sg2002/additional/vision/src/maix_camera.cpp
Normal file
425
support/sg2002/additional/vision/src/maix_camera.cpp
Normal file
@@ -0,0 +1,425 @@
|
||||
/**
|
||||
* @author neucrack@sipeed, lxowalle@sipeed
|
||||
* @copyright Sipeed Ltd 2023-
|
||||
* @license Apache 2.0
|
||||
* @update 2023.9.8: Add framework, create this file.
|
||||
*/
|
||||
|
||||
|
||||
#include "maix_camera.hpp"
|
||||
#include <dirent.h>
|
||||
#ifdef PLATFORM_LINUX
|
||||
#include "maix_camera_v4l2.hpp"
|
||||
#endif
|
||||
#ifdef PLATFORM_MAIXCAM
|
||||
#include "maix_camera_mmf.hpp"
|
||||
#endif
|
||||
|
||||
namespace maix::camera
|
||||
{
|
||||
static bool set_regs_flag = false;
|
||||
|
||||
std::vector<std::string> list_devices()
|
||||
{
|
||||
// find to /dev/video*
|
||||
std::vector<std::string> devices;
|
||||
std::string path = "/dev";
|
||||
DIR *dir = opendir(path.c_str());
|
||||
if (dir == NULL)
|
||||
{
|
||||
return devices;
|
||||
}
|
||||
struct dirent *ptr;
|
||||
while ((ptr = readdir(dir)) != NULL)
|
||||
{
|
||||
if (ptr->d_type == DT_CHR)
|
||||
{
|
||||
std::string name = ptr->d_name;
|
||||
if (name.find("video") != std::string::npos)
|
||||
{
|
||||
devices.push_back( path + "/" + name );
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
// sort devices with name
|
||||
std::sort(devices.begin(), devices.end());
|
||||
// print devices
|
||||
for (size_t i = 0; i < devices.size(); i++)
|
||||
{
|
||||
log::debug("find device: %s\n", devices[i].c_str());
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
void set_regs_enable(bool enable) {
|
||||
set_regs_flag = enable;
|
||||
}
|
||||
|
||||
err::Err Camera::show_colorbar(bool enable)
|
||||
{
|
||||
// only set variable now
|
||||
// should control camera to show colorbar
|
||||
_show_colorbar = enable;
|
||||
return err::ERR_NONE;
|
||||
}
|
||||
|
||||
static void generate_colorbar(image::Image &img)
|
||||
{
|
||||
int width = img.width();
|
||||
int height = img.height();
|
||||
int step = width / 8;
|
||||
int color_step = 255 / 7;
|
||||
int color = 0;
|
||||
uint8_t colors[8][3] = {
|
||||
{255, 255, 255},
|
||||
{255, 0, 0},
|
||||
{255, 127, 0},
|
||||
{255, 255, 0},
|
||||
{0, 255, 0},
|
||||
{0, 0, 255},
|
||||
{143, 0, 255},
|
||||
{0, 0, 0},
|
||||
};
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
image::Color _color(colors[i][0], colors[i][1], colors[i][2], 0, image::FMT_RGB888);
|
||||
img.draw_rect(i * step, 0, step, height, _color, -1);
|
||||
color += color_step;
|
||||
}
|
||||
}
|
||||
#ifdef PLATFORM_LINUX
|
||||
static char * _get_device(const char *device)
|
||||
{
|
||||
if (device)
|
||||
{
|
||||
return (char *)device;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::string> devices = list_devices();
|
||||
err::check_bool_raise(devices.size() > 0, "No camera device");
|
||||
return (char *)devices[0].c_str();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Camera::Camera(int width, int height, image::Format format, const char *device, int fps, int buff_num, bool open)
|
||||
{
|
||||
err::Err e;
|
||||
err::check_bool_raise(_check_format(format), "Format not support");
|
||||
|
||||
if (format == image::Format::FMT_RGB888 && width * height * 3 > 640 * 640 * 3) {
|
||||
log::warn("Note that we do not recommend using large resolution RGB888 images, which can take up a lot of memory!\r\n");
|
||||
}
|
||||
|
||||
_width = (width == -1) ? 640 : width;
|
||||
_height = (height == -1) ? 480 : height;
|
||||
_format = format;
|
||||
_fps = (fps == -1) ? 30 : fps;
|
||||
_buff_num = buff_num;
|
||||
|
||||
_show_colorbar = false;
|
||||
_open_set_regs = set_regs_flag;
|
||||
_impl = NULL;
|
||||
|
||||
#ifdef PLATFORM_LINUX
|
||||
_device = _get_device(device);
|
||||
_impl = new CameraV4L2(_device, _width, _height, _format, _buff_num);
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_MAIXCAM
|
||||
_device = "";
|
||||
_impl = new CameraCviMmf(_device, _width, _height, _format, _buff_num);
|
||||
#endif
|
||||
|
||||
if (open) {
|
||||
e = this->open(_width, _height, _format, _buff_num);
|
||||
|
||||
// err::check_raise(e, "camera open failed");
|
||||
}
|
||||
}
|
||||
|
||||
Camera::Camera(const char *device, CameraBase *base, int width, int height, image::Format format, int fps, int buff_num, bool open)
|
||||
{
|
||||
err::Err e;
|
||||
err::check_bool_raise(_check_format(format), "Format not support");
|
||||
|
||||
_width = (width == -1) ? 640 : width;
|
||||
_height = (height == -1) ? 480 : height;
|
||||
_format = format;
|
||||
_fps = (fps == -1) ? 30 : fps;
|
||||
_buff_num = buff_num;
|
||||
|
||||
_show_colorbar = false;
|
||||
_open_set_regs = set_regs_flag;
|
||||
_impl = base;
|
||||
|
||||
if (open) {
|
||||
e = this->open(_width, _height, _format, _buff_num);
|
||||
err::check_raise(e, "camera open failed");
|
||||
}
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
{
|
||||
if (this->is_opened()) {
|
||||
this->close();
|
||||
}
|
||||
#ifdef PLATFORM_LINUX
|
||||
delete (CameraV4L2*)_impl;
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_MAIXCAM
|
||||
delete (CameraCviMmf*)_impl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Camera::restart(int width, int height, image::Format format, const char *device, int fps, int buff_num, bool open)
|
||||
{
|
||||
if (this->is_opened()) {
|
||||
this->close();
|
||||
}
|
||||
#ifdef PLATFORM_LINUX
|
||||
delete (CameraV4L2*)_impl;
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_MAIXCAM
|
||||
delete (CameraCviMmf*)_impl;
|
||||
#endif
|
||||
|
||||
err::Err e;
|
||||
err::check_bool_raise(_check_format(format), "Format not support");
|
||||
|
||||
if (format == image::Format::FMT_RGB888 && width * height * 3 > 640 * 640 * 3) {
|
||||
log::warn("Note that we do not recommend using large resolution RGB888 images, which can take up a lot of memory!\r\n");
|
||||
}
|
||||
|
||||
_width = (width == -1) ? 640 : width;
|
||||
_height = (height == -1) ? 480 : height;
|
||||
_format = format;
|
||||
_fps = (fps == -1) ? 30 : fps;
|
||||
_buff_num = buff_num;
|
||||
|
||||
_show_colorbar = false;
|
||||
_open_set_regs = set_regs_flag;
|
||||
_impl = NULL;
|
||||
|
||||
#ifdef PLATFORM_LINUX
|
||||
_device = _get_device(device);
|
||||
_impl = new CameraV4L2(_device, _width, _height, _format, _buff_num);
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_MAIXCAM
|
||||
_device = "";
|
||||
_impl = new CameraCviMmf(_device, _width, _height, _format, _buff_num);
|
||||
#endif
|
||||
|
||||
if (open) {
|
||||
e = this->open(_width, _height, _format, _buff_num);
|
||||
|
||||
// err::check_raise(e, "camera open failed");
|
||||
}
|
||||
}
|
||||
|
||||
int Camera::get_ch_nums()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
int Camera::get_channel()
|
||||
{
|
||||
if (_impl == NULL)
|
||||
return err::ERR_NOT_INIT;
|
||||
|
||||
if (!this->is_opened()) {
|
||||
return err::ERR_NOT_OPEN;
|
||||
}
|
||||
|
||||
return _impl->get_channel();
|
||||
}
|
||||
|
||||
bool Camera::_check_format(image::Format format) {
|
||||
if (format == image::FMT_RGB888 || format == image::FMT_BGR888
|
||||
|| format == image::FMT_RGBA8888 || format == image::FMT_BGRA8888
|
||||
|| format == image::FMT_YVU420SP || format == image::FMT_GRAYSCALE) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
err::Err Camera::open(int width, int height, image::Format format, int fps, int buff_num)
|
||||
{
|
||||
if (_impl == NULL)
|
||||
return err::Err::ERR_RUNTIME;
|
||||
|
||||
int width_tmp = (width == -1) ? _width : width;
|
||||
int height_tmp = (height == -1) ? _height : height;
|
||||
image::Format format_tmp = (format == image::FMT_INVALID) ? _format : format;
|
||||
int fps_tmp = (fps == -1) ? 30 : fps;
|
||||
int buff_num_tmp =( buff_num == -1) ? _buff_num : buff_num;
|
||||
|
||||
err::check_bool_raise(_check_format(format_tmp), "Format not support");
|
||||
|
||||
if (this->is_opened()) {
|
||||
if (width == width_tmp && height == height_tmp && format == format_tmp && fps == fps_tmp && buff_num == buff_num_tmp) {
|
||||
return err::ERR_NONE;
|
||||
}
|
||||
this->close(); // Get new param, close and reopen
|
||||
}
|
||||
|
||||
_width = width_tmp;
|
||||
_height = height_tmp;
|
||||
_fps = fps_tmp;
|
||||
_buff_num = buff_num_tmp;
|
||||
_format = format_tmp;
|
||||
_format_impl = _format;
|
||||
if(!_impl->is_support_format(_format))
|
||||
{
|
||||
if(_impl->is_support_format(image::FMT_RGB888))
|
||||
_format_impl = image::FMT_RGB888;
|
||||
else if(_impl->is_support_format(image::FMT_BGR888))
|
||||
_format_impl = image::FMT_BGR888;
|
||||
else if(_impl->is_support_format(image::FMT_YVU420SP))
|
||||
_format_impl = image::FMT_YVU420SP;
|
||||
else if(_impl->is_support_format(image::FMT_YUV420SP))
|
||||
_format_impl = image::FMT_YUV420SP;
|
||||
else if(_impl->is_support_format(image::FMT_RGBA8888))
|
||||
_format_impl = image::FMT_RGBA8888;
|
||||
else if(_impl->is_support_format(image::FMT_BGRA8888))
|
||||
_format_impl = image::FMT_BGRA8888;
|
||||
else if(_impl->is_support_format(image::FMT_GRAYSCALE))
|
||||
_format_impl = image::FMT_GRAYSCALE;
|
||||
else
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
|
||||
return _impl->open(_width, _height, _format_impl, _buff_num);;
|
||||
}
|
||||
|
||||
void Camera::close()
|
||||
{
|
||||
if (this->is_closed())
|
||||
return;
|
||||
|
||||
_impl->close();
|
||||
}
|
||||
|
||||
camera::Camera *Camera::add_channel(int width, int height, image::Format format, int fps, int buff_num, bool open)
|
||||
{
|
||||
err::check_bool_raise(_check_format(format), "Format not support");
|
||||
|
||||
int width_tmp = (width == -1) ? _width : width;
|
||||
int height_tmp = (height == -1) ? _height : height;
|
||||
image::Format format_tmp = (format == image::Format::FMT_INVALID) ? _format : format;
|
||||
int fps_tmp = (fps == -1) ? _fps : fps;
|
||||
int buff_num_tmp = buff_num == -1 ? _buff_num : buff_num;
|
||||
|
||||
Camera *cam = NULL;
|
||||
if (_impl) {
|
||||
CameraBase *cam_base = _impl->add_channel(width_tmp, height_tmp, format_tmp, buff_num);
|
||||
err::check_bool_raise(cam_base, "Unable to add a new channel. Please check the maximum number of supported channels.");
|
||||
cam = new Camera(_device.c_str(), cam_base, width_tmp, height_tmp, format_tmp, fps_tmp, buff_num_tmp, open);
|
||||
}
|
||||
return cam;
|
||||
}
|
||||
|
||||
bool Camera::is_opened()
|
||||
{
|
||||
if (_impl == NULL)
|
||||
return false;
|
||||
|
||||
return _impl->is_opened();
|
||||
}
|
||||
|
||||
image::Image *Camera::read(void *buff, size_t buff_size, bool block)
|
||||
{
|
||||
if (!this->is_opened()) {
|
||||
// err::Err e = open(_width, _height, _format, _buff_num);
|
||||
// err::check_raise(e, "open camera failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_show_colorbar) {
|
||||
image::Image *img = new image::Image(_width, _height);
|
||||
generate_colorbar(*img);
|
||||
err::check_null_raise(img, "camera read failed");
|
||||
return img;
|
||||
} else {
|
||||
// it's better all done by impl to faster read, but if impl not support, we have to convert it
|
||||
if(_format_impl == _format)
|
||||
{
|
||||
image::Image *img = _impl->read(buff, buff_size);
|
||||
// err::check_null_raise(img, "camera read failed");
|
||||
return img;
|
||||
}
|
||||
else
|
||||
{
|
||||
image::Image *img = _impl->read();
|
||||
image::Image *img2 = img->to_format(_format, buff, buff_size);
|
||||
delete img;
|
||||
// err::check_null_raise(img2, "camera read failed");
|
||||
return img2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Camera::clear_buff()
|
||||
{
|
||||
if (_impl == NULL)
|
||||
return;
|
||||
_impl->clear_buff();
|
||||
}
|
||||
|
||||
void Camera::skip_frames(int num)
|
||||
{
|
||||
if (_impl == NULL)
|
||||
return;
|
||||
for(int i = 0; i < num; i++)
|
||||
{
|
||||
image::Image *img = _impl->read();
|
||||
delete img;
|
||||
}
|
||||
}
|
||||
|
||||
err::Err Camera::set_resolution(int width, int height)
|
||||
{
|
||||
err::Err e;
|
||||
if (_impl == NULL)
|
||||
return err::ERR_NOT_INIT;
|
||||
|
||||
if (this->is_opened()) {
|
||||
this->close();
|
||||
}
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
e = this->open(_width, _height, _format, _buff_num);
|
||||
err::check_raise(e, "camera open failed");
|
||||
return err::ERR_NONE;
|
||||
}
|
||||
|
||||
int Camera::hmirror(int value) {
|
||||
if (_impl == NULL)
|
||||
return err::ERR_NOT_INIT;
|
||||
|
||||
if (!this->is_opened()) {
|
||||
return err::ERR_NOT_OPEN;
|
||||
}
|
||||
|
||||
return _impl->hmirror(value);
|
||||
}
|
||||
|
||||
int Camera::vflip(int value) {
|
||||
if (_impl == NULL)
|
||||
return err::ERR_NOT_INIT;
|
||||
|
||||
if (!this->is_opened()) {
|
||||
return err::ERR_NOT_OPEN;
|
||||
}
|
||||
|
||||
return _impl->vflip(value);
|
||||
}
|
||||
}
|
||||
|
||||
1654
support/sg2002/additional/vision/src/maix_image.cpp
Normal file
1654
support/sg2002/additional/vision/src/maix_image.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1209
support/sg2002/additional/vision/src/maix_image_ops.cpp
Normal file
1209
support/sg2002/additional/vision/src/maix_image_ops.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user