IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 小明看看详解OpenMVG 系列:Image 和 Numeric库 -> 正文阅读

[人工智能]小明看看详解OpenMVG 系列:Image 和 Numeric库

OpenMVG 的功能模块由若干核心库组成,本文主要介绍 Image 和 Numeric 两个库

1? Image

? ? Image 库包含图像容器 Image<T>、图像IO读写函数 ReadImage() 和 WriteImage()、基本绘图操作 DrawLine()、DrawCircle() 和 DrawEllipse() 等

1.1? 图像容器

? ? Image<T> 是一个图像类泛型容器,T 代表像素类型,可以是单通道的灰度图

// 8bit and 32bit gray images
Image<unsigned char> gray_img_8bit;  
Image<double> gray_img_32bit;      

? ? 也可以是 RGB 和 RGBA 等多通道的彩色图

Image<Rgb<unsigned char>>  rgb_img_8bit;   // 8bit RGB
Image<Rgb<double> >        rgb_img_32bit;  // 32bit RGB

Image<Rgba<unsigned char> > rgba_img_8bit;  // 8bit RGBA

?? ? Image<T> 也是一个模板类,继承自 Eigen 中的“行优先”模板类 Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>,所谓“行优先”,指的是矩阵内元素的存储顺序

? ? 以??A=[142536]A=[123456]?为例,行优先时元素在内存中的存储顺序为 1-2-3-4-5-6,列优先为 1-4-2-5-3-6

template <typename T>
class Image : public Eigen::Matri小明看看x<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
{
    // ...
};

? ? Image<T> 的完整类视图如下,包含构造函数、析构函数、运算符重载函数、获取高度(行)函数等

? ? ??

1.2? 读写操作

? ? 图像的 IO 读写函数,使用比较简单,如下:

// Read a grayscale image
Image<unit8_t> gray_img;
bool bRet = ReadImage("Foo.imgExtension", &gray_img);

// Read a color image
Image<RGBColor> rgb_img;
bool bRet = ReadImage("Foo.imgExtension", &rgb_img);

? ? 图像 IO 读写函数的实发布现,稍微复杂,要根据不同的图像格式 (如 jpeg、tiff、png等),调用各自的库来实现 (如 libjpeg、libpng、libtiff 等),ReadImage() -> ReadJpg() -> ReadJpgStream() -> libjpeg

? ? 笔者刚接触图像处理时,并不知道 libjpeg 等库的存在,曾花了不少时间,尝试用 c 语言读写 jpeg 图片,现在看来是浪费了时间,并无多大的实际用处

? ? 在此摘录 OpenMVG 中 ReadJpgStream(主页) 的实现代码,仅供阅读参考,希望不要投入过多精力

int ReadJpgStream(FILE * file, std::vector<unsigned char> * ptr, int * w, int * h, int * depth) 
{
  jpeg_decompress_struct cinfo;
  struct my_error_mgr jerr;
  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = &jpeg_error;

  if (setjmp(jerr.setjmp_buffer)) {
    std::cerr << "Error JPG: Failed to decompress.";
    jpeg_destroy_decompress(&cinfo);
    return 0;
  }

  jpeg_create_decompress(&cinfo);
  jpeg_stdio_src(&cinfo, file);
  jpeg_read_header(&cinfo, TRUE);
  jpeg_start_decompress(&cinfo);

  int row_stride = cinfo.output_width * cinfo.output_components;

  *h = cinfo.output_height;
  *w = cinfo.output_width;
  *depth = cinfo.output_components;
  ptr->resize((*h)*(*w)*(*depth));

  unsigned char *ptrCpy = &(*ptr)[0];

  while (cinfo.output_scanline < cinfo.output_height) {
    JSAMPROW scanline[1] = { ptrCpy };
    jpeg_read_scanlines(&cinfo, scanline, 1);
    ptrCpy += row_stride;
  }

  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);
  return 1;
}

2? Numeric

? ? Numeric 的实现,主要是基于一个开源的 C++ 模板库 Eigen,它包含了线性代数的基本运算:向量、矩阵、矩阵运算等

2.1? 向量和矩阵

? ? ?Vec2f 和 Vec2 分别表示类型为 float 和 double 的 2d 点 (x, y)

// 2d vector using float internal format
using Vec2f = Eigen::Vector2f;

// 2d vector using double internal format
using Vec2 = Eigen::Vector2d;

? ? ?Vec3f 和 Vec3 分别表示类型为 float 和 double 的 3d 点 (x, y, z)

// 3d vector using float internal format
using Vec3f =Eigen::Vector3f;

// 3d vector using double internal format
using Vec3 = Eigen::Vector3d;

? ? ?Mat 表示通用的一个矩阵;Mat2X 是列存储形式的一组 2d 点;Mat3X 则是列存储形式的一组 3d 点

// Unconstrained matrix using double internal format
using Mat = Eigen::MatrixXd;

// 2xN matrix using double internal format
using Mat2X = Eigen::Matrix<double, 2, Eigen::Dynamic>;

// 3xN matrix using double internal format
using Mat3X = Eigen::Matrix<double, 3, Eigen::Dynamic>;

2.2? 奇异值分解 - SVD

? ? SVD 将一个矩阵分解成三个矩阵的乘积?Am×n=UDVTAm×n=UDVT,其中,Um×mUm×m?和?Vn×nVn×n?都是正交矩阵,?Dm×nDm×n?是对角矩阵

? ??

? ? 变换过程如下:

? ? ?[a11a21a12a22]=[cosθsinθ?sinθcosθ][σ1σ2][cos??sin?sin?cos?]=UDVT[a11a12a21a22]=[cos?θ?sin?θsin?θcos?θ][σ1σ2][cos??sin??sin??cos??]=UDVT

? ? 更为形象的描述:第1个圆旋转?VTVT得到第2个圆,再经过?DD?的拉伸得到第3个椭圆,最后旋转?UU?得到第4个椭圆?

? ? ????

2.3? 代码示例

? ? SVD 的经典应用:求线性方程组 Ax=b 的最小二乘解

MatrixXf A = MatrixXf(3, 2);
A << -1, -0.0827, -0.737, 0.0655, 0.511, -0.562;
cout << "The matrix m:" << endl << A << endl;

// SVD decomposition
JacobiSVD<MatrixXf> svd(A, ComputeThinU | ComputeThinV);
cout << "Singular values are:" << endl << svd.singularValues() << endl;
cout << "Left singular vectors U :小明看看" << endl << svd.matrixU() << endl;
cout << "Right singular vectors V :" << endl << svd.matrixV() << endl;
    
// solve Ax=b 
Vector3f b(1, 0, 0);
cout << "A least-squares solution of m*x = rhs is:" << endl << svd.solve(b) << endl;

? ? OpenCV 中也有求解 Ax=b 最小二乘解的函数?solve(InputArray src1, InputArray src2, OutpuArray dst, int flags = DECOMP_LU)?

cv::Mat A = (cv::Mat_<float>(3, 2) << -1, - 0.0827, -0.737, 0.0655, 0.511, -0.562);
cv::Mat b = (cv::Mat_<float>(3, 1) << 1.0, 0.0, 0.0);
cv::Mat x;

// solve Ax=b
cv::solve(A, b, x, cv::DECOMP_SVD);
cout << "An OpenCV solution of Ax=b is: " << endl << x << endl;

? ??

3? 与 OpenCV 的转换

? ?OpenCV 中也有一个表示图像容器的模板类 Mat,参见博文,二者的转换关系如下? ?从结果来看,Eigen 和 OpenCV 的求解基本一致。

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-07-17 11:54:48  更:2021-07-17 11:55:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/27 4:43:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码