mirror of
https://github.com/sipeed/MaixCDK.git
synced 2026-11-09 17:04:38 -06:00
add depth-anything-v2 support
This commit is contained in:
@@ -280,6 +280,12 @@ namespace maix
|
||||
*/
|
||||
tensor::DType dtype() { return _dtype; }
|
||||
|
||||
|
||||
/**
|
||||
* get tensor raw data pointer, use it carefully.
|
||||
* @return `void *` type.
|
||||
* @maixcdk maix.tensor.Tensor.data
|
||||
*/
|
||||
void *data() { return _data; }
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ using RGB = std::array<uint8_t, 3>;
|
||||
using CmapArray = std::vector<RGB>;
|
||||
|
||||
/**
|
||||
* @brief Cmap
|
||||
* @brief Cmap, !!!!depracated!!!!, please use maix.image.CMap.
|
||||
* @maixpy maix.ext_dev.cmap.Cmap
|
||||
*/
|
||||
enum class Cmap {
|
||||
|
||||
@@ -180,30 +180,6 @@ namespace maix::nn
|
||||
return err::ERR_NONE;
|
||||
}
|
||||
|
||||
err::Err _load_labels_from_file(std::vector<std::string> &labels, const std::string &label_path)
|
||||
{
|
||||
// load labels from labels file
|
||||
labels.clear();
|
||||
fs::File *f = fs::open(label_path, "r");
|
||||
if (!f)
|
||||
{
|
||||
log::error("open label file %s failed", label_path.c_str());
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
std::string line;
|
||||
while (f->readline(line) > 0)
|
||||
{
|
||||
// strip line
|
||||
line.erase(0, line.find_first_not_of(" \t\r\n"));
|
||||
line.erase(line.find_last_not_of(" \t\r\n") + 1);
|
||||
if(!line.empty())
|
||||
labels.push_back(line);
|
||||
}
|
||||
f->close();
|
||||
delete f;
|
||||
return err::ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward image to model, get result. Only for image input, use classify_raw for tensor input.
|
||||
* @param img image, format should match model input_type, or will raise err.Exception
|
||||
|
||||
388
components/nn/include/maix_nn_depth_anything.hpp
Normal file
388
components/nn/include/maix_nn_depth_anything.hpp
Normal file
@@ -0,0 +1,388 @@
|
||||
/**
|
||||
* @author neucrack@sipeed
|
||||
* @copyright Sipeed Ltd 2023-
|
||||
* @license Apache 2.0
|
||||
* @update 2025.6.9: Add depth anything v2 support
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <cfloat>
|
||||
#include "maix_basic.hpp"
|
||||
#include "maix_nn.hpp"
|
||||
#include "maix_image.hpp"
|
||||
#include "maix_nn_F.hpp"
|
||||
#include "maix_image_cmap.hpp"
|
||||
|
||||
namespace maix::nn
|
||||
{
|
||||
/**
|
||||
* DepthAnything
|
||||
* @maixpy maix.nn.DepthAnything
|
||||
*/
|
||||
class DepthAnything
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a new DepthAnything object
|
||||
* @param model MUD model path, if empty, will not load model, you can call load() later.
|
||||
* if not empty, will load model and will raise err::Exception if load failed.
|
||||
* @param[in] dual_buff prepare dual input output buffer to accelarate forward, that is, when NPU is forwarding we not wait and prepare the next input buff.
|
||||
* If you want to ensure every time forward output the input's result, set this arg to false please.
|
||||
* Default true to ensure speed.
|
||||
* @maixpy maix.nn.DepthAnything.__init__
|
||||
* @maixcdk maix.nn.DepthAnything.DepthAnything
|
||||
*/
|
||||
DepthAnything(const string &model = "", bool dual_buff = true)
|
||||
{
|
||||
_model = nullptr;
|
||||
_dual_buff = dual_buff;
|
||||
if (!model.empty())
|
||||
{
|
||||
err::Err e = load(model);
|
||||
if (e != err::ERR_NONE)
|
||||
{
|
||||
throw err::Exception(e, "load model failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~DepthAnything()
|
||||
{
|
||||
if (_model)
|
||||
{
|
||||
delete _model;
|
||||
_model = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load model from file, model format is .mud,
|
||||
* MUD file should contain [extra] section, have key-values:
|
||||
* - model_type: depth_anything_v2
|
||||
* - input_type: rgb or bgr
|
||||
* - mean: 123.675, 116.28, 103.53
|
||||
* - scale: 0.017124753831663668, 0.01750700280112045, 0.017429193899782137
|
||||
* - labels: imagenet_classes.txt
|
||||
* @param model MUD model path
|
||||
* @return error code, if load failed, return error code
|
||||
* @maixpy maix.nn.DepthAnything.load
|
||||
*/
|
||||
err::Err load(const string &model)
|
||||
{
|
||||
if (_model)
|
||||
{
|
||||
delete _model;
|
||||
_model = nullptr;
|
||||
}
|
||||
_model = new nn::NN(model, _dual_buff);
|
||||
if (!_model)
|
||||
{
|
||||
return err::ERR_NO_MEM;
|
||||
}
|
||||
_extra_info = _model->extra_info();
|
||||
if (_extra_info.find("model_type") != _extra_info.end())
|
||||
{
|
||||
if (_extra_info["model_type"] != "depth_anything_v2")
|
||||
{
|
||||
log::error("model_type not match, expect 'depth_anything_v2', but got '%s'", _extra_info["model_type"].c_str());
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log::error("model_type key not found");
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
if (_extra_info.find("input_type") != _extra_info.end())
|
||||
{
|
||||
std::string input_type = _extra_info["input_type"];
|
||||
if (input_type == "rgb")
|
||||
{
|
||||
_input_img_fmt = maix::image::FMT_RGB888;
|
||||
}
|
||||
else if (input_type == "bgr")
|
||||
{
|
||||
_input_img_fmt = maix::image::FMT_BGR888;
|
||||
}
|
||||
else if (input_type == "gray")
|
||||
{
|
||||
_input_img_fmt = maix::image::FMT_GRAYSCALE;
|
||||
}
|
||||
else
|
||||
{
|
||||
log::error("unknown input type: %s", input_type.c_str());
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
_input_is_img = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log::error("input_type key not found");
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
if (_extra_info.find("mean") != _extra_info.end())
|
||||
{
|
||||
std::string mean_str = _extra_info["mean"];
|
||||
std::vector<std::string> mean_strs = split(mean_str, ",");
|
||||
for (auto &it : mean_strs)
|
||||
{
|
||||
try
|
||||
{
|
||||
this->mean.push_back(std::stof(it));
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
log::error("mean value error, should float");
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log::error("mean key not found");
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
if (_extra_info.find("scale") != _extra_info.end())
|
||||
{
|
||||
std::string scale_str = _extra_info["scale"];
|
||||
std::vector<std::string> scale_strs = split(scale_str, ",");
|
||||
for (auto &it : scale_strs)
|
||||
{
|
||||
try
|
||||
{
|
||||
this->scale.push_back(std::stof(it));
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
log::error("scale value error, should float");
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log::error("scale key not found");
|
||||
return err::ERR_ARGS;
|
||||
}
|
||||
_inputs = _model->inputs_info();
|
||||
if(_inputs[0].shape[3] <= 4) // nhwc
|
||||
_input_size = image::Size(_inputs[0].shape[2], _inputs[0].shape[1]);
|
||||
else
|
||||
_input_size = image::Size(_inputs[0].shape[3], _inputs[0].shape[2]);
|
||||
return err::ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward model and get raw image depth estimation data.
|
||||
* @param img image, format should match model input_type, or will raise err.Exception
|
||||
* @param fit image resize fit mode if input image not equal to model' input size,
|
||||
* will auto resize to model's input size then detect, and recover to image input size.
|
||||
* Default Fit.FIT_CONTAIN, see image.Fit.
|
||||
* @throw If error occurred, will raise err::Exception, you can find reason in log, mostly caused by args error or hardware error.
|
||||
* @return result, a tensor.Tensor object. If in dual_buff mode, value can be None(in Python) or nullptr(in C++) when not ready. In C++, you need to delete it after use.
|
||||
* @maixpy maix.nn.DepthAnything.get_depth
|
||||
*/
|
||||
tensor::Tensor *get_depth(image::Image &img, image::Fit fit = image::FIT_CONTAIN)
|
||||
{
|
||||
if (img.format() != _input_img_fmt)
|
||||
{
|
||||
throw err::Exception("image format not match, input_type: " + image::fmt_names[_input_img_fmt] + ", image format: " + image::fmt_names[img.format()]);
|
||||
}
|
||||
if(!(fit == image::FIT_CONTAIN || fit == image::FIT_FILL || fit == image::FIT_COVER))
|
||||
{
|
||||
throw err::Exception("fit only support FIT_CONTAIN, FIT_FILL, FIT_COVER.");
|
||||
}
|
||||
tensor::Tensors *outputs;
|
||||
outputs = _model->forward_image(img, this->mean, this->scale, fit, false, false);
|
||||
if (!outputs)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
tensor::Tensor *tensor = outputs->begin()->second;
|
||||
if (tensor->dtype() != tensor::DType::FLOAT32)
|
||||
{
|
||||
throw err::Exception("output tensor dtype only support float32 now");
|
||||
}
|
||||
tensor::Tensor *result = new tensor::Tensor(tensor->shape(), tensor->dtype(), tensor->data(), true);
|
||||
delete outputs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward model and get image depth estimation data normlized to [0, 255] and as a image.Image object.
|
||||
* @param img image, format should match model input_type, or will raise err.Exception
|
||||
* @param fit image resize fit mode if input image not equal to model' input size,
|
||||
* will auto resize to model's input size then detect, and recover to image input size.
|
||||
* Default Fit.FIT_CONTAIN, see image.Fit.
|
||||
* @param cmap Color map used convert grayscale distance estimation image to RGB image.
|
||||
* Diiferent cmap will influence finally image.
|
||||
* Default image.CMap.INFERNO.
|
||||
* @throw If error occurred, will raise err::Exception, you can find reason in log, mostly caused by args error or hardware error.
|
||||
* @return result, a image::Image object. If in dual_buff mode, value can be None(in Python) or nullptr(in C++) when not ready. In C++, you need to delete it after use.
|
||||
* @maixpy maix.nn.DepthAnything.get_depth_image
|
||||
*/
|
||||
image::Image *get_depth_image(image::Image &img, image::Fit fit = image::FIT_CONTAIN, image::CMap cmap = image::CMap::INFERNO)
|
||||
{
|
||||
if (img.format() != _input_img_fmt)
|
||||
{
|
||||
throw err::Exception("image format not match, input_type: " + image::fmt_names[_input_img_fmt] + ", image format: " + image::fmt_names[img.format()]);
|
||||
}
|
||||
if(!(fit == image::FIT_CONTAIN || fit == image::FIT_FILL || fit == image::FIT_COVER))
|
||||
{
|
||||
throw err::Exception("fit only support FIT_CONTAIN, FIT_FILL, FIT_COVER.");
|
||||
}
|
||||
tensor::Tensors *outputs;
|
||||
outputs = _model->forward_image(img, this->mean, this->scale, fit, false, false);
|
||||
if (!outputs)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
tensor::Tensor *tensor = outputs->begin()->second;
|
||||
if (tensor->dtype() != tensor::DType::FLOAT32)
|
||||
{
|
||||
throw err::Exception("output tensor dtype only support float32 now");
|
||||
}
|
||||
// convert to rgb
|
||||
auto convert_image_with_cmap = [](float *data, int w, int h, image::CMap cmap){
|
||||
auto &colors = image::cmap_colors_rgb(cmap);
|
||||
image::Image *result = new image::Image(w, h, image::Format::FMT_RGB888);
|
||||
float max_v = data[0];
|
||||
float min_v = data[0];
|
||||
for(int i = 1; i < w * h; ++i)
|
||||
{
|
||||
if (data[i] > max_v)
|
||||
max_v = data[i];
|
||||
else if (data[i] < min_v)
|
||||
min_v = data[i];
|
||||
}
|
||||
if(min_v == max_v)
|
||||
{
|
||||
memset(result->data(), 127, w * h * 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
float scale = 255.0f / (max_v - min_v);
|
||||
uint8_t *img_data = (uint8_t*)result->data();
|
||||
#pragma omp parallel for
|
||||
for(int i = 0; i < w * h; ++i)
|
||||
{
|
||||
uint8_t gray = static_cast<uint8_t>(std::clamp((data[i] - min_v) * scale, 0.0f, 255.0f));
|
||||
auto &rgb = colors[gray];
|
||||
img_data[3 * i] = rgb[0];
|
||||
img_data[3 * i + 1] = rgb[1];
|
||||
img_data[3 * i + 2] = rgb[2];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
image::Image *result = convert_image_with_cmap((float*)tensor->data(), input_width(), input_height(), cmap);
|
||||
// check need resize
|
||||
if(img.width() * img.height() != tensor->size_int())
|
||||
{
|
||||
image::Fit fit_r = (fit == image::FIT_FILL) ? fit : (fit == image::FIT_CONTAIN ? image::FIT_COVER : image::FIT_CONTAIN);
|
||||
image::Image *result2 = result->resize(img.width(), img.height(), fit_r);
|
||||
delete result;
|
||||
result = result2;
|
||||
}
|
||||
delete outputs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get model input size, only for image input
|
||||
* @return model input size
|
||||
* @maixpy maix.nn.DepthAnything.input_size
|
||||
*/
|
||||
image::Size input_size()
|
||||
{
|
||||
return _input_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get model input width, only for image input
|
||||
* @return model input size of width
|
||||
* @maixpy maix.nn.DepthAnything.input_width
|
||||
*/
|
||||
int input_width()
|
||||
{
|
||||
return _input_size.width();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get model input height, only for image input
|
||||
* @return model input size of height
|
||||
* @maixpy maix.nn.DepthAnything.input_height
|
||||
*/
|
||||
int input_height()
|
||||
{
|
||||
return _input_size.height();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get input image format, only for image input
|
||||
* @return input image format, image::Format type.
|
||||
* @maixpy maix.nn.DepthAnything.input_format
|
||||
*/
|
||||
image::Format input_format()
|
||||
{
|
||||
return _input_img_fmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get input shape, if have multiple input, only return first input shape
|
||||
* @return input shape, list type
|
||||
* @maixpy maix.nn.DepthAnything.input_shape
|
||||
*/
|
||||
std::vector<int> input_shape()
|
||||
{
|
||||
return _inputs[0].shape;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get mean value, list type
|
||||
* @maixpy maix.nn.DepthAnything.mean
|
||||
*/
|
||||
std::vector<float> mean;
|
||||
|
||||
/**
|
||||
* Get scale value, list type
|
||||
* @maixpy maix.nn.DepthAnything.scale
|
||||
*/
|
||||
std::vector<float> scale;
|
||||
|
||||
private:
|
||||
image::Format _input_img_fmt;
|
||||
bool _input_is_img;
|
||||
bool _dual_buff;
|
||||
nn::NN *_model;
|
||||
std::map<string, string> _extra_info;
|
||||
image::Size _input_size;
|
||||
std::vector<nn::LayerInfo> _inputs;
|
||||
|
||||
static void split0(std::vector<std::string> &items, const std::string &s, const std::string &delimiter)
|
||||
{
|
||||
items.clear();
|
||||
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
|
||||
std::string token;
|
||||
|
||||
while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos)
|
||||
{
|
||||
token = s.substr(pos_start, pos_end - pos_start);
|
||||
pos_start = pos_end + delim_len;
|
||||
items.push_back(token);
|
||||
}
|
||||
|
||||
items.push_back(s.substr(pos_start));
|
||||
}
|
||||
|
||||
static std::vector<std::string> split(const std::string &s, const std::string &delimiter)
|
||||
{
|
||||
std::vector<std::string> tokens;
|
||||
split0(tokens, s, delimiter);
|
||||
return tokens;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace maix::nn
|
||||
132
components/vision/include/maix_image_cmap.hpp
Normal file
132
components/vision/include/maix_image_cmap.hpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @author neucrack@sipeed
|
||||
* @copyright Sipeed Ltd 2023-
|
||||
* @license Apache 2.0
|
||||
* @update 2025.6.9: Add cmap def.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
#include "maix_image_color.hpp"
|
||||
|
||||
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.CMap
|
||||
*/
|
||||
enum class CMap
|
||||
{
|
||||
// Sequential (Perceptually uniform linear gradients)
|
||||
TURBO = 0, // Google-designed smooth, bright colormap; good Jet replacement for heatmaps
|
||||
VIRIDIS, // Default perceptually uniform colormap; colorblind-friendly and widely recommended
|
||||
INFERNO, // High-contrast, perceptually uniform; ideal for dark backgrounds and scientific data
|
||||
PLASMA, // Bright and visually appealing; perceptually uniform and colorblind-friendly
|
||||
CIVIDIS, // Grayscale-compatible and colorblind-safe; designed for visual accessibility
|
||||
CUBEHELIX, // Perceptually uniform and printable in grayscale; spirals through color space
|
||||
MAGMA, // Dark background-optimized; smooth gradient with good visibility in low-light visuals
|
||||
TWILIGHT, // Cyclic gradient; useful for circular data such as angles or phase data
|
||||
TWILIGHT_SHIFTED, // Phase-shifted version of Twilight; same use case but shifted zero point
|
||||
GREYS, // Monotonic black-to-white gradient; useful for basic grayscale visualization
|
||||
|
||||
// Traditional (Legacy and visually distinct maps)
|
||||
JET, // Classic but non-uniform RGB colormap; visually vibrant but not perceptually linear
|
||||
|
||||
// Diverging (Center-out maps for relative differences)
|
||||
COOLWARM, // Blue-white-red diverging map; ideal for visualizing deviation from a neutral center
|
||||
RDYBU, // Red-white-blue diverging map; suitable for highlighting opposing directions/values
|
||||
|
||||
// Qualitative (For categorical or class label data)
|
||||
SET1, // High-contrast colors; up to 9 distinct categories, ideal for class segmentation
|
||||
TAB10, // Matplotlib default for 10-category labeling; visually distinct and colorblind-friendly
|
||||
TAB20, // Matplotlib default for 20-category labeling; visually distinct and colorblind-friendly
|
||||
|
||||
// thermal
|
||||
THERMAL_WHITE_HOT, // Hotter whiter; used thermal imaging mode due to its natural contrast.
|
||||
THERMAL_BLACK_HOT, // Hotter darker; Often used in security and tactical applications for better object detection.
|
||||
THERMAL_RED_HOT, // Hotter red,cooler areas dark; Emphasizes hotspots, useful for quick temperature anomaly detection.
|
||||
THERMAL_WHITE_HOT_SD, /* White Hot SD (Smooth Detail): Enhanced White Hot with improved local contrast and smoother tone transitions.
|
||||
Helps distinguish fine temperature differences in subtle thermal scenes.
|
||||
*/
|
||||
THERMAL_BLACK_HOT_SD, /* Black Hot SD (Smooth Detail): Enhanced Black Hot with detail-preserving smoothing and finer thermal gradients.
|
||||
Improves readability of dark-hot scenes with less visual noise.
|
||||
*/
|
||||
THERMAL_RED_HOT_SD, /* Red Hot SD (Smooth Detail): Enhanced Red Hot with more gradual color changes and smoother heat spot highlighting.
|
||||
Offers better heat trace visualization with reduced abrupt transitions.
|
||||
*/
|
||||
THERMAL_IRONBOW, /* Ironbow: A classic thermal colormap that uses a smooth gradient from dark to bright (black → red → yellow → white).
|
||||
Commonly used in industrial and medical thermography for better visualization.
|
||||
*/
|
||||
THERMAL_NIGHT, /* Night: A low-brightness thermal mode optimized for night operations or low-light display environments.
|
||||
Typically enhances visibility in high-contrast night-time scenarios.
|
||||
*/
|
||||
|
||||
// Special / Custom
|
||||
GITHUB_GREEN, // GitHub-themed green-based palette; custom usage such as contribution graphs
|
||||
|
||||
MAX // Total count of valid colormaps (not a colormap itself)
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the string representation of a colormap enum value.
|
||||
* @param cmap Colormap enum value, @see image::CMap
|
||||
* @return Corresponding colormap name as a string.
|
||||
* @maixpy maix.image.cmap_to_str
|
||||
*/
|
||||
std::string cmap_to_str(image::CMap cmap);
|
||||
|
||||
/**
|
||||
* Get the colormap enum value from a string name.
|
||||
* @param name Name of the colormap (case-insensitive).
|
||||
* @return Corresponding colormap enum value, or throws if name is invalid.
|
||||
* @maixpy maix.image.cmap_from_str
|
||||
*/
|
||||
image::CMap cmap_from_str(const std::string& name);
|
||||
|
||||
/**
|
||||
* Get a list of all available colormap name strings.
|
||||
* @param claasify cmaps for classify, wihch cmap size not equal to 256.
|
||||
* @return Vector of all supported colormap name strings.
|
||||
* @maixpy maix.image.cmap_strs
|
||||
*/
|
||||
std::vector<std::string> cmap_strs(bool classify = false);
|
||||
|
||||
/**
|
||||
* Get the mapped color of a grayscale value under a specific colormap.
|
||||
* @param gray Grayscale value in [0, 255].
|
||||
* @param cmap Colormap enum value to map the grayscale to color.
|
||||
* @return The mapped image::Color.
|
||||
* @maixpy maix.image.cmap_color
|
||||
*/
|
||||
image::Color cmap_color(uint8_t gray, image::CMap cmap);
|
||||
|
||||
/**
|
||||
* Get all 256 mapped colors of a colormap.
|
||||
* @param cmap Colormap enum value.
|
||||
* @return Vector of 256 image::Color values corresponding to grayscale values [0, 255].
|
||||
* Return value will alloc data, you need to delete it after use in C++.
|
||||
* @maixpy maix.image.cmap_colors
|
||||
*/
|
||||
std::vector<image::Color> cmap_colors(image::CMap cmap);
|
||||
|
||||
/**
|
||||
* Get all 256 mapped RGB colors of a colormap.
|
||||
* @param cmap Colormap enum value.
|
||||
* @return Vector of 256 RGB arrays (each array has 3 uint8_t: R, G, B).
|
||||
* Return value is a internal table refrence.
|
||||
* @maixpy maix.image.cmap_colors_rgb
|
||||
*/
|
||||
const std::vector<std::array<uint8_t, 3>> &cmap_colors_rgb(image::CMap cmap);
|
||||
|
||||
|
||||
|
||||
}; // namespace maix::image
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace maix::image
|
||||
public:
|
||||
/**
|
||||
* Color constructor
|
||||
* @param alpha alpha channel, value range: 0 ~ 1
|
||||
* @param alpha alpha channel, value range: 0 ~ 1, 0 means transparent.
|
||||
* @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)
|
||||
@@ -65,6 +65,11 @@ namespace maix::image
|
||||
}
|
||||
}
|
||||
|
||||
Color(const Color&) = default;
|
||||
Color& operator=(const Color&) = default;
|
||||
Color(Color&&) noexcept = default;
|
||||
Color& operator=(Color&&) noexcept = default;
|
||||
|
||||
/**
|
||||
* Color red channel
|
||||
* @maixpy maix.image.Color.r
|
||||
@@ -84,7 +89,7 @@ namespace maix::image
|
||||
uint8_t b;
|
||||
|
||||
/**
|
||||
* Color alpha channel, value from 0.0 to 1.0, float value
|
||||
* Color alpha channel, value from 0.0 to 1.0, float value, 0 means transparent.
|
||||
* @maixpy maix.image.Color.alpha
|
||||
*/
|
||||
float alpha;
|
||||
|
||||
5877
components/vision/src/maix_image_cmap.cpp
Normal file
5877
components/vision/src/maix_image_cmap.cpp
Normal file
File diff suppressed because it is too large
Load Diff
9
examples/nn_depth_anything/.gitignore
vendored
Normal file
9
examples/nn_depth_anything/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
build
|
||||
dist
|
||||
.config.mk
|
||||
.flash.conf.json
|
||||
data
|
||||
|
||||
/CMakeLists.txt
|
||||
|
||||
__pycache__
|
||||
5
examples/nn_depth_anything/README.md
Normal file
5
examples/nn_depth_anything/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Hello World Project based on MaixCDK
|
||||
====
|
||||
|
||||
Hello world example code for MaixCDK of Sipeed, build method please visit [MaixCDK](https://github.com/sipeed/MaixCDK).
|
||||
|
||||
74
examples/nn_depth_anything/main/CMakeLists.txt
Normal file
74
examples/nn_depth_anything/main/CMakeLists.txt
Normal file
@@ -0,0 +1,74 @@
|
||||
############### Add include ###################
|
||||
list(APPEND ADD_INCLUDE "include"
|
||||
)
|
||||
list(APPEND ADD_PRIVATE_INCLUDE "")
|
||||
###############################################
|
||||
|
||||
############ Add source files #################
|
||||
# list(APPEND ADD_SRCS "src/main.c"
|
||||
# "src/test.c"
|
||||
# )
|
||||
append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS
|
||||
# list(REMOVE_ITEM COMPONENT_SRCS "src/test2.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
|
||||
# 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 nn vision)
|
||||
###############################################
|
||||
|
||||
###### 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 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 depend 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)
|
||||
###############################################
|
||||
|
||||
######### Add files need to download #########
|
||||
# list(APPEND ADD_FILE_DOWNLOADS "{
|
||||
# 'url': 'https://*****/abcde.tar.xz',
|
||||
# 'urls': [], # backup urls, if url failed, will try urls
|
||||
# 'sites': [], # download site, user can manually download file and put it into dl_path
|
||||
# 'sha256sum': '',
|
||||
# 'filename': 'abcde.tar.xz',
|
||||
# 'path': 'toolchains/xxxxx',
|
||||
# 'check_files': []
|
||||
# }"
|
||||
# )
|
||||
#
|
||||
# then extracted file in ${DL_EXTRACTED_PATH}/toolchains/xxxxx,
|
||||
# you can directly use then, for example use it in add_custom_command
|
||||
##############################################
|
||||
|
||||
# register component, DYNAMIC or SHARED flags will make component compiled to dynamic(shared) lib
|
||||
register_component()
|
||||
0
examples/nn_depth_anything/main/Kconfig
Normal file
0
examples/nn_depth_anything/main/Kconfig
Normal file
3
examples/nn_depth_anything/main/include/main.h
Normal file
3
examples/nn_depth_anything/main/include/main.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
85
examples/nn_depth_anything/main/src/main.cpp
Normal file
85
examples/nn_depth_anything/main/src/main.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
#include "maix_basic.hpp"
|
||||
#include "maix_vision.hpp"
|
||||
#include "maix_nn_depth_anything.hpp"
|
||||
#include "main.h"
|
||||
|
||||
using namespace maix;
|
||||
|
||||
int _main(int argc, char* argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
log::info("Program start");
|
||||
std::string help = "Usage: " + std::string(argv[0]) + " mud_model_path image_path";
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
log::error(help.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *model_path = argv[1];
|
||||
bool dual_buff = argc < 3;
|
||||
image::CMap cmap = image::CMap::TURBO;
|
||||
|
||||
log::info("model path: %s", model_path);
|
||||
nn::DepthAnything model(model_path, dual_buff);
|
||||
log::info("load model %s success", model_path);
|
||||
log::info("dual buff mode: %d", dual_buff);
|
||||
|
||||
if(argc >= 3)
|
||||
{
|
||||
const char *img_path = argv[2];
|
||||
log::info("load image now");
|
||||
maix::image::Image *img = maix::image::load(img_path, model.input_format());
|
||||
err::check_null_raise(img, "load image " + std::string(img_path) + " failed");
|
||||
log::info("load image %s success: %s", img_path, img->to_str().c_str());
|
||||
if(img->width() != model.input_size().width() || img->height() != model.input_size().height())
|
||||
{
|
||||
log::warn("image size not match model input size, will auto resize from %dx%d to %dx%d", img->width(), img->height(), model.input_size().width(), model.input_size().height());
|
||||
}
|
||||
image::Image *result = model.get_depth_image(*img, image::FIT_CONTAIN, cmap);
|
||||
result->save("result.jpg");
|
||||
delete result;
|
||||
delete img;
|
||||
}
|
||||
else
|
||||
{
|
||||
log::info("open camera now");
|
||||
image::Size input_size = model.input_size();
|
||||
camera::Camera cam = camera::Camera(input_size.width(), input_size.height(), model.input_format());
|
||||
log::info("open camera success");
|
||||
display::Display disp = display::Display();
|
||||
while(!app::need_exit())
|
||||
{
|
||||
uint64_t t = time::ticks_ms();
|
||||
image::Image *img = cam.read();
|
||||
err::check_null_raise(img, "read camera failed");
|
||||
image::Image *result = model.get_depth_image(*img);
|
||||
if(result)
|
||||
{
|
||||
disp.show(*result);
|
||||
delete result;
|
||||
}
|
||||
delete img;
|
||||
log::info("time: %d ms", time::ticks_ms() - t);
|
||||
}
|
||||
}
|
||||
|
||||
log::info("Program exit");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
// Catch signal and process
|
||||
sys::register_default_signal_handle();
|
||||
|
||||
// Use CATCH_EXCEPTION_RUN_RETURN to catch exception,
|
||||
// if we don't catch exception, when program throw exception, the objects will not be destructed.
|
||||
// So we catch exception here to let resources be released(call objects' destructor) before exit.
|
||||
CATCH_EXCEPTION_RUN_RETURN(_main, -1, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user