Refactor: Rename NanoKVM to BatchuKVM and update server URL
This commit is contained in:
6
support/sg2002/additional/kvm/CMakeLists.txt
Normal file
6
support/sg2002/additional/kvm/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
list(APPEND ADD_REQUIREMENTS vision basic peripheral)
|
||||
list(APPEND ADD_INCLUDE "include")
|
||||
|
||||
append_srcs_dir(ADD_SRCS "src")
|
||||
|
||||
register_component(DYNAMIC)
|
||||
0
support/sg2002/additional/kvm/Kconfig
Normal file
0
support/sg2002/additional/kvm/Kconfig
Normal file
82
support/sg2002/additional/kvm/include/kvm_vision.h
Normal file
82
support/sg2002/additional/kvm/include/kvm_vision.h
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
|
||||
#ifndef KVM_VISION_H_
|
||||
#define KVM_VISION_H_
|
||||
|
||||
#include "kvm_mmf.hpp"
|
||||
#include "maix_camera.hpp"
|
||||
#include "maix_basic.hpp"
|
||||
|
||||
#include "maix_i2c.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <fcntl.h> /* low-level i/o */
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
// #include "kvm_mmf.hpp"
|
||||
|
||||
#define IMG_BUFFER_FULL -3
|
||||
#define IMG_VENC_ERROR -2
|
||||
#define IMG_NOT_EXIST -1
|
||||
#define IMG_MJPEG_TYPE 0
|
||||
#define IMG_H264_TYPE_SPS 1
|
||||
#define IMG_H264_TYPE_PPS 2
|
||||
#define IMG_H264_TYPE_IF 3
|
||||
#define IMG_H264_TYPE_PF 4
|
||||
|
||||
#define NORMAL_RES 0
|
||||
#define NEW_RES 1
|
||||
#define UNSUPPORT_RES 2
|
||||
#define UNKNOWN_RES 3
|
||||
#define ERROR_RES 4
|
||||
|
||||
void kvmv_init(uint8_t _debug_info_en = 0);
|
||||
void set_venc_auto_recyc(uint8_t _enable);
|
||||
/**********************************************************************************
|
||||
* @name kvmv_read_img
|
||||
* @author Sipeed BuGu
|
||||
* @date 2024/10/25
|
||||
* @version R1.0
|
||||
* @brief Acquire the encoded image with auto init
|
||||
* @param _width @input: Output image width
|
||||
* @param _height @input: Output image height
|
||||
* @param _type @input: Encode type
|
||||
* @param _qlty @input: MJPEG: (50-100) | H264: (500-10000)
|
||||
* @param _pp_kvm_data @output: Encode data
|
||||
* @param _p_kvmv_data_size @output: Encode data size
|
||||
* @return
|
||||
-7: HDMI INPUT RES ERROR
|
||||
-6: Unsupported resolution, please modify it in the host settings.
|
||||
-5: Retrieving image, please wait
|
||||
-4: Modifying image resolution, please wait
|
||||
-3: img buffer full
|
||||
-2: VENC Errorl
|
||||
-1: No images were acquired
|
||||
0: Acquire MJPEG encoded images
|
||||
1: Acquire H264 encoded images(SPS)[Deprecated]
|
||||
2: Acquire H264 encoded images(PPS)[Deprecated]
|
||||
3: Acquire H264 encoded images(I)
|
||||
4: Acquire H264 encoded images(P)
|
||||
5: IMG not changed
|
||||
**********************************************************************************/
|
||||
int kvmv_read_img(uint16_t _width, uint16_t _height, uint8_t _type, uint16_t _qlty, uint8_t** _pp_kvm_data, uint32_t* _p_kvmv_data_size);
|
||||
int free_kvmv_data(uint8_t ** _pp_kvm_data);
|
||||
void free_all_kvmv_data();
|
||||
void set_h264_gop(uint8_t _gop);
|
||||
void set_frame_detact(uint8_t _frame_detact);
|
||||
void kvmv_deinit();
|
||||
uint8_t kvmv_hdmi_control(uint8_t _en);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // KVM_VISION_H_
|
||||
1857
support/sg2002/additional/kvm/src/kvm_vision.cpp
Normal file
1857
support/sg2002/additional/kvm/src/kvm_vision.cpp
Normal file
File diff suppressed because it is too large
Load Diff
66
support/sg2002/additional/kvm_mmf/CMakeLists.txt
Normal file
66
support/sg2002/additional/kvm_mmf/CMakeLists.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
list(APPEND ADD_REQUIREMENTS basic ini)
|
||||
list(APPEND ADD_INCLUDE "include")
|
||||
|
||||
# sophgo-middleware
|
||||
set(middleware_src_path "${CMAKE_CURRENT_SOURCE_DIR}/../3rd_party/sophgo-middleware/sophgo-middleware")
|
||||
|
||||
|
||||
set(source_dir "src")
|
||||
append_srcs_dir(ADD_SRCS "${source_dir}")
|
||||
|
||||
# middleware
|
||||
set(middleware_include_dir .
|
||||
${middleware_src_path}/v2/component/panel/${CONFIG_SOPHGO_MIDDLEWARE_CHIP}
|
||||
${middleware_src_path}/v2/include
|
||||
${middleware_src_path}/v2/include/isp/${CONFIG_SOPHGO_MIDDLEWARE_CHIP}
|
||||
${middleware_src_path}/v2/sample/common
|
||||
${middleware_src_path}/v2/uapi
|
||||
${middleware_src_path}/v2/3rdparty/inih
|
||||
${middleware_src_path}/v2/modules/ive/include/
|
||||
)
|
||||
list(APPEND ADD_INCLUDE ${middleware_include_dir})
|
||||
set_property(SOURCE ${middleware_include_dir} PROPERTY GENERATED 1)
|
||||
|
||||
append_srcs_dir(middleware_src_dir ${middleware_src_path}/v2/sample/common
|
||||
${middleware_src_path}/v2/component/isp/sensor/sg200x/lontium_lt6911
|
||||
)
|
||||
list(APPEND ADD_SRCS ${middleware_src_dir}
|
||||
"${source_dir}/kvm_mmf.cpp")
|
||||
set_property(SOURCE ${middleware_src_dir} PROPERTY GENERATED 1)
|
||||
|
||||
set(middleware_static_lib_file "")
|
||||
list(APPEND ADD_STATIC_LIB ${middleware_static_lib_file})
|
||||
set_property(SOURCE ${middleware_static_lib_file} PROPERTY GENERATED 1)
|
||||
|
||||
set(mmf_lib_dir ${middleware_src_path}/v2/lib)
|
||||
|
||||
if(CONFIG_SOPHGO_MIDDLEWARE_C_LIBRARY STREQUAL "musl")
|
||||
set(middleware_dynamic_lib_file ${mmf_lib_dir}/libcvi_bin.so
|
||||
${mmf_lib_dir}/libae.so
|
||||
${mmf_lib_dir}/libaf.so
|
||||
${mmf_lib_dir}/libawb.so
|
||||
${mmf_lib_dir}/libcvi_bin_isp.so
|
||||
${mmf_lib_dir}/libisp_algo.so
|
||||
${mmf_lib_dir}/libisp.so
|
||||
${mmf_lib_dir}/libsys.so
|
||||
${mmf_lib_dir}/libvdec.so
|
||||
${mmf_lib_dir}/libvenc.so
|
||||
${mmf_lib_dir}/libvpu.so
|
||||
${mmf_lib_dir}/3rd/libini.so)
|
||||
elseif(CONFIG_SOPHGO_MIDDLEWARE_C_LIBRARY STREQUAL "glibc")
|
||||
set(middleware_dynamic_lib_file ${mmf_lib_dir}/libcvi_vb.so
|
||||
${mmf_lib_dir}/libcvi_sys.so
|
||||
${mmf_lib_dir}/libcvi_debug.so
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "No sophgo middleware c library support, please check menuoconfig to select c library")
|
||||
endif()
|
||||
list(APPEND ADD_DYNAMIC_LIB ${middleware_dynamic_lib_file})
|
||||
set_property(SOURCE ${middleware_dynamic_lib_file} PROPERTY GENERATED 1)
|
||||
|
||||
list(APPEND ADD_DEFINITIONS_PRIVATE -DSENSOR_LONTIUM_LT6911
|
||||
-DSENSOR2_TYPE=LONTIUM_LT6911_2M_60FPS_8BIT)
|
||||
|
||||
|
||||
register_component(DYNAMIC)
|
||||
32
support/sg2002/additional/kvm_mmf/Kconfig
Normal file
32
support/sg2002/additional/kvm_mmf/Kconfig
Normal file
@@ -0,0 +1,32 @@
|
||||
# sophgo middleware version major minor patch
|
||||
menu "sophgo middleware version"
|
||||
config SOPHGO_MIDDLEWARE_CHIP
|
||||
string "sophgo chip"
|
||||
default "cv181x"
|
||||
help
|
||||
sophgo chip. cv180x or cv181x
|
||||
|
||||
config SOPHGO_MIDDLEWARE_C_LIBRARY
|
||||
string "sophgo c standard library"
|
||||
default "musl"
|
||||
help
|
||||
sophgo c standard library. glibc or musl
|
||||
|
||||
config SOPHGO_MIDDLEWARE_VERSION_MAJOR
|
||||
int "sophgo middleware package major version"
|
||||
default 0
|
||||
help
|
||||
sophgo middleware package major version, 0 means auto select according to board
|
||||
|
||||
config SOPHGO_MIDDLEWARE_VERSION_MINOR
|
||||
int "sophgo middleware package minor version"
|
||||
default 0
|
||||
help
|
||||
sophgo middleware package minor version
|
||||
|
||||
config SOPHGO_MIDDLEWARE_VERSION_PATCH
|
||||
int "sophgo middleware package patch version"
|
||||
default 4
|
||||
help
|
||||
sophgo middleware package patch version
|
||||
endmenu
|
||||
68
support/sg2002/additional/kvm_mmf/include/kvm_mmf.hpp
Normal file
68
support/sg2002/additional/kvm_mmf/include/kvm_mmf.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef __KVM_MMF_HPP__
|
||||
#define __KVM_MMF_HPP__
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t *data[8];
|
||||
int data_size[8];
|
||||
int count;
|
||||
} mmf_stream_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t type; // 0, jpg; 1, h265; 2, h264
|
||||
int w;
|
||||
int h;
|
||||
int fmt;
|
||||
uint8_t jpg_quality; // jpeg
|
||||
int gop; // h264
|
||||
int intput_fps; // h264
|
||||
int output_fps; // h264
|
||||
int bitrate; // h264
|
||||
} mmf_venc_cfg_t;
|
||||
|
||||
// init sys
|
||||
int mmf_init(void);
|
||||
int mmf_deinit(void);
|
||||
int mmf_try_deinit(bool force);
|
||||
bool mmf_is_init(void);
|
||||
|
||||
// manage vi channels(vi->vpssgroup->vpss->frame)
|
||||
int mmf_get_vi_unused_channel(void);
|
||||
int mmf_vi_init(void);
|
||||
int mmf_vi_deinit(void);
|
||||
int mmf_add_vi_channel_with_enc(int ch, int width, int height, int format);
|
||||
int mmf_add_vi_channel(int ch, int width, int height, int format);
|
||||
int mmf_del_vi_channel(int ch);
|
||||
int mmf_del_vi_channel_all(void);
|
||||
int mmf_reset_vi_channel(int ch, int width, int height, int format);
|
||||
bool mmf_vi_chn_is_open(int ch);
|
||||
int mmf_vi_aligned_width(int ch);
|
||||
void mmf_set_vi_hmirror(int ch, bool en);
|
||||
void mmf_set_vi_vflip(int ch, bool en);
|
||||
void mmf_get_vi_hmirror(int ch, bool *en);
|
||||
void mmf_get_vi_vflip(int ch, bool *en);
|
||||
|
||||
// get vi frame
|
||||
int mmf_vi_frame_pop(int ch, void **data, int *len, int *width, int *height, int *format);
|
||||
void mmf_vi_frame_free(int ch);
|
||||
|
||||
// invert format
|
||||
int mmf_invert_format_to_maix(int mmf_format);
|
||||
int mmf_invert_format_to_mmf(int maix_format);
|
||||
|
||||
// venc
|
||||
int mmf_enc_jpg_init(int ch, int w, int h, int format, int quality);
|
||||
int mmf_enc_jpg_deinit(int ch);
|
||||
int mmf_enc_jpg_push(int ch, uint8_t *data, int w, int h, int format);
|
||||
int mmf_enc_jpg_push_with_quality(int ch, uint8_t *data, int w, int h, int format, int quality);
|
||||
int mmf_enc_jpg_pop(int ch, uint8_t **data, int *size);
|
||||
int mmf_enc_jpg_free(int ch);
|
||||
int mmf_add_venc_channel(int ch, mmf_venc_cfg_t *cfg);
|
||||
int mmf_del_venc_channel(int ch);
|
||||
int mmf_del_venc_channel_all();
|
||||
int mmf_venc_push(int ch, uint8_t *data, int w, int h, int format);
|
||||
int mmf_venc_pop(int ch, mmf_stream_t *stream);
|
||||
int mmf_venc_free(int ch);
|
||||
|
||||
#endif // __KVM_MMF_HPP__
|
||||
2352
support/sg2002/additional/kvm_mmf/src/kvm_mmf.cpp
Normal file
2352
support/sg2002/additional/kvm_mmf/src/kvm_mmf.cpp
Normal file
File diff suppressed because it is too large
Load Diff
322
support/sg2002/additional/peripheral/port/maixcam/maix_i2c.cpp
Normal file
322
support/sg2002/additional/peripheral/port/maixcam/maix_i2c.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
/**
|
||||
* @author neucrack@sipeed, lxowalle@sipeed
|
||||
* @copyright Sipeed Ltd 2023-
|
||||
* @license Apache 2.0
|
||||
* @update 2023.9.8: Add framework, create this file.
|
||||
*/
|
||||
|
||||
|
||||
#include "maix_i2c.hpp"
|
||||
#include "maix_basic.hpp"
|
||||
#include "cstdio"
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define DEV_PATH "/dev/i2c-%d"
|
||||
|
||||
namespace maix::peripheral::i2c
|
||||
{
|
||||
|
||||
std::vector<int> list_devices()
|
||||
{
|
||||
std::vector<int> data;
|
||||
// list all files in /dev, find i2c-*
|
||||
std::vector<std::string> *files = fs::listdir("/dev");
|
||||
for (auto &file : *files)
|
||||
{
|
||||
if (file.find("i2c-") != std::string::npos)
|
||||
{
|
||||
try
|
||||
{
|
||||
data.push_back(std::stoi(file.substr(4)));
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
log::error("i2c bus id %s format error", file.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
delete files;
|
||||
return data;
|
||||
}
|
||||
|
||||
I2C::I2C(int id, i2c::Mode mode, int freq, i2c::AddrSize addr_size)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), DEV_PATH, id);
|
||||
if(access(buf, F_OK) == 0){
|
||||
if (mode == i2c::SLAVE)
|
||||
{
|
||||
throw err::Exception(err::Err::ERR_NOT_IMPL, "i2c::SLAVE mode not implemented");
|
||||
}
|
||||
if (addr_size != i2c::SEVEN_BIT)
|
||||
{
|
||||
throw err::Exception(err::Err::ERR_NOT_IMPL, "addr_size " + std::to_string(addr_size) + " not support");
|
||||
}
|
||||
|
||||
int fd = ::open(buf, O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
throw err::Exception(err::Err::ERR_IO, "open " + std::string(buf) + " failed");
|
||||
}
|
||||
_fd = fd;
|
||||
_freq = freq;
|
||||
_mode = mode;
|
||||
_addr_size = addr_size;
|
||||
} else {
|
||||
printf("not exit i2c\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
I2C::~I2C()
|
||||
{
|
||||
if (_fd > 0)
|
||||
{
|
||||
::close(_fd);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> I2C::scan(int addr)
|
||||
{
|
||||
std::vector<int> data;
|
||||
int addr_start = 0x08;
|
||||
int addr_end = 0x77;
|
||||
if(addr > 0)
|
||||
{
|
||||
addr_start = addr;
|
||||
addr_end = addr;
|
||||
}
|
||||
|
||||
if (_mode != i2c::Mode::MASTER)
|
||||
{
|
||||
log::error("Only for master mode");
|
||||
return data;
|
||||
}
|
||||
|
||||
switch (_addr_size)
|
||||
{
|
||||
case i2c::AddrSize::SEVEN_BIT:
|
||||
for (int address = addr_start; address <= addr_end; ++address)
|
||||
{
|
||||
if (::ioctl(_fd, I2C_SLAVE, address) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned char buffer[1];
|
||||
if (::read(_fd, buffer, sizeof(buffer)) >= 0)
|
||||
{
|
||||
data.push_back(address);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log::error("bit %d not support", _addr_size);
|
||||
return data;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
int I2C::writeto(int addr, const uint8_t *data, int len)
|
||||
{
|
||||
if (_mode != i2c::Mode::MASTER)
|
||||
{
|
||||
log::error("Only for master mode");
|
||||
return (int)-err::Err::ERR_NOT_PERMIT;
|
||||
}
|
||||
|
||||
if (0 != ioctl(_fd, I2C_SLAVE, addr))
|
||||
{
|
||||
// log::error("set slave address failed");
|
||||
return (int)-err::Err::ERR_IO;
|
||||
}
|
||||
|
||||
if (len != ::write(_fd, data, len))
|
||||
{
|
||||
log::error("write failed");
|
||||
return (int)-err::Err::ERR_IO;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int I2C::writeto(int addr, const std::vector<unsigned char> data)
|
||||
{
|
||||
return writeto(addr, data.data(), (int)data.size());
|
||||
}
|
||||
|
||||
int I2C::writeto(int addr, const Bytes &data)
|
||||
{
|
||||
return writeto(addr, data.data, (int)data.size());
|
||||
}
|
||||
|
||||
Bytes* I2C::readfrom(int addr, int len)
|
||||
{
|
||||
Bytes *data = new Bytes(nullptr, len);
|
||||
|
||||
if (_mode != i2c::Mode::MASTER)
|
||||
{
|
||||
log::error("Only for master mode");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (0 != ioctl(_fd, I2C_SLAVE, addr))
|
||||
{
|
||||
// log::error("set slave address failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (len != ::read(_fd, data->data, len))
|
||||
{
|
||||
log::error("read failed");
|
||||
delete data;
|
||||
return nullptr;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
int I2C::writeto_mem(int addr, int mem_addr, const uint8_t *data, int len, int mem_addr_size, bool mem_addr_le)
|
||||
{
|
||||
if (_mode != i2c::Mode::MASTER)
|
||||
{
|
||||
log::error("Only for master mode");
|
||||
return (int)-err::Err::ERR_NOT_PERMIT;
|
||||
}
|
||||
if(mem_addr_size % 8 != 0)
|
||||
{
|
||||
log::error("mem_addr_size must be multiple of 8");
|
||||
return (int)-err::Err::ERR_IO;
|
||||
}
|
||||
|
||||
if (0 != ioctl(_fd, I2C_SLAVE, addr))
|
||||
{
|
||||
// log::error("set slave address failed");
|
||||
return (int)-err::Err::ERR_IO;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> data_final;
|
||||
|
||||
if(mem_addr_size == 8)
|
||||
{
|
||||
data_final.push_back((unsigned char)mem_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mem_addr_le)
|
||||
{
|
||||
for(int i = 0; i < mem_addr_size / 8; i++)
|
||||
{
|
||||
data_final.push_back((unsigned char)(mem_addr & 0xff));
|
||||
mem_addr >>= 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < mem_addr_size / 8; i++)
|
||||
{
|
||||
data_final.push_back((unsigned char)(mem_addr >> (8 * (mem_addr_size / 8 - i - 1))));
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
data_final.push_back(data[i]);
|
||||
}
|
||||
int write_len = ::write(_fd, data_final.data(), data_final.size());
|
||||
if (data_final.size() != (size_t)write_len)
|
||||
{
|
||||
log::error("write failed, write_len: %d", write_len);
|
||||
return (int)-err::Err::ERR_IO;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int I2C::writeto_mem(int addr, int mem_addr, const std::vector<unsigned char> data, int mem_addr_size, bool mem_addr_le)
|
||||
{
|
||||
return writeto_mem(addr, mem_addr, data.data(), (int)data.size(), mem_addr_size, mem_addr_le);
|
||||
}
|
||||
|
||||
int I2C::writeto_mem(int addr, int mem_addr, const Bytes &data, int mem_addr_size, bool mem_addr_le)
|
||||
{
|
||||
return writeto_mem(addr, mem_addr, data.data, (int)data.size(), mem_addr_size, mem_addr_le);
|
||||
}
|
||||
|
||||
Bytes* I2C::readfrom_mem(int addr, int mem_addr, int len, int mem_addr_size, bool mem_addr_le)
|
||||
{
|
||||
// write mem_addr and restart to read
|
||||
if (_mode != i2c::Mode::MASTER)
|
||||
{
|
||||
log::error("Only for master mode");
|
||||
return nullptr;
|
||||
}
|
||||
if(mem_addr_size % 8 != 0)
|
||||
{
|
||||
log::error("mem_addr_size must be multiple of 8");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// write mem_addr first and restart to read
|
||||
if (0 != ioctl(_fd, I2C_SLAVE, addr))
|
||||
{
|
||||
// log::error("set slave address failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> data_final;
|
||||
if(mem_addr_size == 8)
|
||||
{
|
||||
data_final.push_back((unsigned char)mem_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mem_addr_le)
|
||||
{
|
||||
for(int i = 0; i < mem_addr_size / 8; i++)
|
||||
{
|
||||
data_final.push_back((unsigned char)(mem_addr & 0xff));
|
||||
mem_addr >>= 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for(int i = 0; i < mem_addr_size / 8; i++)
|
||||
{
|
||||
data_final.push_back((unsigned char)(mem_addr >> (8 * (mem_addr_size / 8 - i - 1))));
|
||||
}
|
||||
}
|
||||
}
|
||||
// write read with I2C_RDWR
|
||||
struct i2c_msg msgs[2];
|
||||
msgs[0].addr = addr;
|
||||
msgs[0].flags = 0;
|
||||
msgs[0].len = data_final.size();
|
||||
msgs[0].buf = data_final.data();
|
||||
|
||||
Bytes *data = new Bytes(nullptr, len);
|
||||
msgs[1].addr = addr;
|
||||
msgs[1].flags = I2C_M_RD;
|
||||
msgs[1].len = len;
|
||||
msgs[1].buf = data->data;
|
||||
|
||||
struct i2c_rdwr_ioctl_data msgset;
|
||||
msgset.msgs = msgs;
|
||||
msgset.nmsgs = 2;
|
||||
|
||||
int read_len = ioctl(_fd, I2C_RDWR, &msgset);
|
||||
if (read_len != 2)
|
||||
{
|
||||
log::error("read failed");
|
||||
delete data;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
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