shape_based_matching lineMod开源代码学习

news2024/11/25 9:35:29

github开源代码地址:

https://github.com/meiqua/shape_based_matching

针对匹配精度问题,原作者采用了sub-pixel + icp的方法进行了最后的finetune,涉及到的相关原理可以查看:亚像素边缘提取与ICP2D的理解 - 知乎

涉及到的论文:

[1] Carsten Steger:Unbiased extraction of curvilinear structures from 2D and 3D images.

[2] Linear Least-Squares Optimization for Point-to-Plane ICP Surface Registration

https://download.csdn.net/download/lipeng19930407/87932688

简单记录一下查看代码过程中存在疑惑的点:

1、linemod论文中,梯度扩散是以当前像素为中心点,从r范围的邻域进行梯度扩散。

 而代码中的实现:

/**
 * \brief Spread binary labels in a quantized image.
 *
 * Implements section 2.3 "Spreading the Orientations."
 *
 * \param[in]  src The source 8-bit quantized image.
 * \param[out] dst Destination 8-bit spread image.
 * \param      T   Sampling step. Spread labels T/2 pixels in each direction.
 */
static void spread(const Mat& src, Mat& dst, int T)
{
  // Allocate and zero-initialize spread (OR'ed) image
  dst = Mat::zeros(src.size(), CV_8U);

  // Fill in spread gradient image (section 2.3)
  for (int r = 0; r < T; ++r)
  {
    int height = src.rows - r;
    for (int c = 0; c < T; ++c)
    {
      orUnaligned8u(&src.at<unsigned char>(r, c), static_cast<int>(src.step1()), dst.ptr(),
                    static_cast<int>(dst.step1()), src.cols - c, height);
    }
  }
}

此处的实现,目标点位将其右下[0,T]范围内的梯度都进行了或操作,即某梯度只向其左上方T大小的范围内进行了扩散,与下文中的T间隔采样暗合,

类似于粗略匹配,且针对噪音或微小形变具备较好的鲁棒性,但因此匹配精度上有所欠缺,才有了后续的icp+subpixel finetune。

2、similarity计算的位置点数

代码如下:

/**
 * \brief Compute similarity measure for a given template at each sampled image location.
 *
 * Uses linear memories to compute the similarity measure as described in Fig. 7.
 *
 * \param[in]  linear_memories Vector of 8 linear memories, one for each label.
 * \param[in]  templ           Template to match against.
 * \param[out] dst             Destination 8-bit similarity image of size (W/T, H/T).
 * \param      size            Size (W, H) of the original input image.
 * \param      T               Sampling step.
 */
static void similarity(const std::vector<Mat>& linear_memories, const Template& templ,
                Mat& dst, Size size, int T)
{
  // 63 features or less is a special case because the max similarity per-feature is 4.
  // 255/4 = 63, so up to that many we can add up similarities in 8 bits without worrying
  // about overflow. Therefore here we use _mm_add_epi8 as the workhorse, whereas a more
  // general function would use _mm_add_epi16.
  CV_Assert(templ.features.size() <= 63);
  /// @todo Handle more than 255/MAX_RESPONSE features!!

  // Decimate input image size by factor of T
  int W = size.width / T;
  int H = size.height / T;

  // Feature dimensions, decimated by factor T and rounded up
  int wf = (templ.width - 1) / T + 1;
  int hf = (templ.height - 1) / T + 1;

  // Span is the range over which we can shift the template around the input image
  int span_x = W - wf;
  int span_y = H - hf;

  // Compute number of contiguous (in memory) pixels to check when sliding feature over
  // image. This allows template to wrap around left/right border incorrectly, so any
  // wrapped template matches must be filtered out!
  int template_positions = span_y * W + span_x + 1; // why add 1?
  //int template_positions = (span_y - 1) * W + span_x; // More correct?

  /// @todo In old code, dst is buffer of size m_U. Could make it something like
  /// (span_x)x(span_y) instead?
  dst = Mat::zeros(H, W, CV_8U);
  uchar* dst_ptr = dst.ptr<uchar>();

#if CV_SSE2
  volatile bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2);
#if CV_SSE3
  volatile bool haveSSE3 = checkHardwareSupport(CV_CPU_SSE3);
#endif
#endif

  // Compute the similarity measure for this template by accumulating the contribution of
  // each feature
  for (int i = 0; i < (int)templ.features.size(); ++i)
  {
    // Add the linear memory at the appropriate offset computed from the location of
    // the feature in the template
    Feature f = templ.features[i];
    // Discard feature if out of bounds
    /// @todo Shouldn't actually see x or y < 0 here?
    if (f.x < 0 || f.x >= size.width || f.y < 0 || f.y >= size.height)
      continue;
    const uchar* lm_ptr = accessLinearMemory(linear_memories, f, T, W);

    // Now we do an aligned/unaligned add of dst_ptr and lm_ptr with template_positions elements
    int j = 0;
    // Process responses 16 at a time if vectorization possible
#if CV_SSE2
#if CV_SSE3
    if (haveSSE3)
    {
      // LDDQU may be more efficient than MOVDQU for unaligned load of next 16 responses
      for ( ; j < template_positions - 15; j += 16)
      {
        __m128i responses = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(lm_ptr + j));
        __m128i* dst_ptr_sse = reinterpret_cast<__m128i*>(dst_ptr + j);
        *dst_ptr_sse = _mm_add_epi8(*dst_ptr_sse, responses);
      }
    }
    else
#endif
    if (haveSSE2)
    {
      // Fall back to MOVDQU
      for ( ; j < template_positions - 15; j += 16)
      {
        __m128i responses = _mm_loadu_si128(reinterpret_cast<const __m128i*>(lm_ptr + j));
        __m128i* dst_ptr_sse = reinterpret_cast<__m128i*>(dst_ptr + j);
        *dst_ptr_sse = _mm_add_epi8(*dst_ptr_sse, responses);
      }
    }
#endif
    for ( ; j < template_positions; ++j)
      dst_ptr[j] = uchar(dst_ptr[j] + lm_ptr[j]);
  }
}

模板也是T间隔滑动后,在采样点位置计算similarity的。这样可以充分使用 Spread T 以及 Restructuring the way the response images S 所带来的便利,使得匹配速度更快。

以上是阅读论文+代码时存在疑惑,记录一下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/666251.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Precision Neuroscience提出第7层皮层接口:可扩展的微创脑机接口平台

大脑皮层包含六层结构&#xff0c;美国精密神经科学公司&#xff08;Precision Neuroscience Corporation&#xff09;的研究人员提出了第7层皮层接口&#xff1a;可拓展的微创脑机接口平台。构建了一种模块化的和可拓展的脑机接口平台&#xff0c;包括高通量薄膜电极阵列和微创…

新加坡市场扩张指南:品牌布局策略与挑战解析

随着全球化的发展和市场竞争的加剧&#xff0c;越来越多的企业开始考虑将业务拓展到新的市场。其中&#xff0c;新加坡作为一个经济繁荣、政治稳定、文化多元的国家&#xff0c;成为许多品牌出海的首选目的地之一。然而&#xff0c;要在这个激烈竞争的市场中取得成功&#xff0…

绘制stm32最小系统板

原理图&#xff1a; 不使用串口烧录&#xff0c;所以BOOT0和BOOT1都接地。 VDD&#xff1a;就是单片机的供电电压。 VDDA&#xff1a;VDD后面有个A&#xff0c;AAnalog&#xff0c;表示模拟的意思&#xff0c;就是芯片内部模拟器件的工作电压。 VSSA&#xff1a;表示模拟器件…

2023 Softing暑期培训计划

通过以实践为导向的培训课程提高能力 Softing将在2023年暑期为您提供全面的培训课程。在Softing线上研讨会中&#xff0c;您将体验到结构紧凑的培训课程&#xff0c;包含实用的用户问题讨论以及完善的理论知识交流&#xff0c;而无需学习冗长而枯燥的标准。无论您是初学者还是…

Unittest二次开发实战

目录 前言 unittest.TestResult类简介 TestResult类定制目标 实现步骤 测试结果summary格式规划 单个用例结果格式规划 用例tags和level的实现 根据测试方法对象获取用例代码 单个用例结果类的实现 TestResult属性及初始化方法 测试开始和测试结束 用例开始和用例结束 1. 重写恢…

Python面向对象编程2-面向过程的银行账号模拟程序 项目2.3 单个账户完整项目版本1

项目总目标&#xff1a;用面向过程思想设计一个简单的银行账号模拟程序。本次将迭代多个程序版本&#xff0c;每个版本都将添加更多功能。虽然这些程序没有达到发布的质量标准&#xff0c;但整个项目的目的是关注于代码如何与一个或多个银行账户的数据进行交互。 分析项目的必…

Windows11 WSL子系统ubuntu22.04 修改hostname

大家都知道以往我们修改 Linux系统的 hostname只要修改 /etc/hostname 这个文件中的名字即可&#xff0c;但是在WSL中修改该文件是无法生效的。 要修改Hostname并使它生效&#xff0c;我们必须修改 /etc/wsl.conf 文件。 编辑配置文件 sudo vi /etc/wsl.conf修改参数 将 ho…

SQL优化--如何定位慢查询?

目录 概述 检测方案 方案一&#xff1a;开源工具 方案二&#xff1a;MySQL自带慢日志 面试回答 大纲 范例 概述 在SQL中&#xff0c;“慢查询”是指执行速度较慢的数据库查询操作。 一般来说聚合查询&#xff0c;多表查询&#xff0c;表数据量过大查询&#xff0c;深度…

埃及极简史

埃及全称为阿拉伯埃及共和国&#xff0c;位于北非东部&#xff0c;领土还包括苏伊士运河以东、亚洲西南端的西奈半岛&#xff0c;埃及既是亚、非之间的陆地交通要冲&#xff0c;也是大西洋于印度洋之间海上航线的捷径&#xff0c;战略位置十分重要。 古埃及是古代四大文明古国之…

龙蜥白皮书精选:Ancert——硬件兼容性验证与守护

文/硬件兼容性 SIG Ancert 是龙蜥操作系统硬件兼容性测试套件&#xff0c;致力于验证硬件设备集成商等厂商发布的整机服务器和各种板卡外设与龙蜥操作系统 不同版本之间的兼容性&#xff0c;推动社区发行版在各种硬件设备上的适配&#xff0c;围绕龙蜥操作系统建立完善的硬件生…

Linux运维监控学习笔记5

监控项和应用集&#xff08;重点&#xff09; 监控项&#xff08;item&#xff09;&#xff1a;监控项是从主机收集的信息。一个监控项是一个独立的子标&#xff0c;代表收集数据或监控的最小的单位。 应用集&#xff08;applications&#xff09;&#xff1a;代表多个监控项…

手写数字识别Python+TensorFlow+CNN卷积神经网络【完整代码系统】

一、介绍 手写数字识别系统&#xff0c;使用Python语言&#xff0c;基于TensorFlow搭建CNN卷积神经网络算法对数据集进行训练&#xff0c;最后得到模型&#xff0c;并基于FLask搭建网页端界面&#xff0c;基于Pyqt5搭建桌面端可视化界面。 二、效果展示 三、演示视频完整代码…

【面试题】MySQL的面试题-分组后数据的处理

有一张业务表 data busi&#xff0c;字段为 id,业务号 busi no 以及编码 busi code,请写出根据busi code 将 busi no 合并去重的 sal。数据: 要求最后的结果为&#xff1a; 这个问题怎么解决呢&#xff1f; 其实解决这个问题的关键是分组后的数据合并&#xff0c;这里需要使用…

热加载工具spring-boot-devtools,使页面修改不重启服务器可以实时更新选择和创建数据库(谷粒商城)

阿丹&#xff1a; 希望可以通过工具进行来进行代码修改的时候能避免重启服务。来加快代码进度。 在pom.xml中添加spring-boot-devtools依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifact…

FI 创建资产和 子资产 BAPI_FIXEDASSET_OVRTAKE_CREATE

AS01 AS11 对应的BAPI 都是 BAPI_FIXEDASSET_OVRTAKE_CREATE 创建子资产有个标记CREATESUBNUMBER

PV180R1K1T1NMMC德国产派克柱塞泵

PV180R1K1T1NMMC德国产派克柱塞泵 派克柱塞泵的介绍&#xff1a; PARKER柱塞泵根据倾斜元件的不同&#xff0c;有斜盘式和斜轴式两种。斜盘式是斜盘相对回转的缸体有一倾斜角度&#xff0c;而引起柱塞在泵缸中往复运动。传动轴轴线和缸体轴线是一致的。这种结构较简单&#x…

async_await异常捕获

写在前面 不知道大家项目里面是怎么处理 async/await 的异常&#xff0c;我斗胆在我们项目里翻了一下&#xff0c;发现大量使用 try-catch 来处理 async/await 异常。 首先说明一下&#xff0c; try-catch 处理并没有什么问题&#xff0c;我只是觉得这么写代码会有点乱&#x…

如何设计一个高效的分布式日志服务平台

作者 | 百度智能小程序团队 导读 本文首先介绍了分布式服务下日志服务建设的挑战&#xff0c;然后介绍了下业内ELK的通用解决方案及与天眼日志服务的差异性&#xff0c;接下来详细介绍了天眼日志服务平台的整体架构&#xff0c;如何做采集、传输、检索、隔离、清理等机制的&…

自定义element-table列表展示(可设置按钮权限)

<template><!-- 二次封装表格&#xff0c; 仅支持单选 :style"{ height: height }"--><div class"self_table"><el-table:data"tableData"style"width: 100%"v-loading"loading"stripeselection-chang…

苹果手机备份占内存吗 苹果手机备份到电脑怎么操作

苹果手机备份占内存吗&#xff1f;实际上&#xff0c;苹果手机备份并不占用本机内存。在使用苹果手机的过程中&#xff0c;备份是一个必要的操作&#xff0c;可以避免丢失重要的数据或者恢复丢失的数据。但是有些用户可能会担心备份会占用手机的内存&#xff0c;从而影响手机的…