积分图的优化
来源:互联网 发布:c语言逻辑表达式 编辑:程序博客网 时间:2024/05/29 08:57
原文:13行代码实现最快速最高效的积分图像算法。
Tips:
1.某个点的积分图反应的是原图中此位置左上角所有像素之和,这里是的累加和是不包括这个点像素本身的,那么,对于原图的第一行和第一列的所有像素,其对应位置的积分图就应该是0, 这样考虑到所有的像素,为了能容纳最后一列和最后一行的情况,最终的积分图就应该是 (W + 1) X (H + 1)大小。
2.优化方式:
原始算法 列优化 行优化
分析:
行优化最优,相比于列优化,更符合图像数据在计算机中的存储顺序,因此并且在计算过程中无需申请额外空间保存各列像素之和,只需一个变量保存行像素之和便可!详见开源软件scantailor里的push函数。
3.在反汇编中,max和min充分利用了条件按传送指令比如cmovg,cmovl,而一般的if语句很大程度上会调用jmp指令的(当然和常数比较一般编译也会用条件传送替代的,比如和0比较),jmp指令是比较耗时的。
开源软件scantailor里的积分图算法的实现:
(调用的时候先调用beginRow定位行指针,然后循环调用push推入该行的像素值,所有行循环完毕就计算完成,然后可以调用sum计算区域累加和。)
/** * \brief Provides the sum of values in a sub-rectangle of a 2D array in constant time. * * Suppose you have a MxN array of some values. Now if we are not going to * alter it, but are going to calculate the sum of values in various * rectangular sub-regions, it's best to use an integral image for this purpose. * We construct it once, with complexity of O(M*N), and then obtain the sum * of values in a rectangular sub-region in O(1). * * \note Template parameter T must be large enough to hold the sum of all * values in the array. */template<typename T>class IntegralImage{ DECLARE_NON_COPYABLE(IntegralImage)public: IntegralImage(int width, int height); explicit IntegralImage(QSize const& size); ~IntegralImage(); /** * \brief To be called before pushing new row data. */ void beginRow(); /** * \brief Push a single value to the integral image. * * Values must be pushed row by row, starting from row 0, and from * column to column within each row, starting from column 0. * At the beginning of a row, a call to beginRow() must be made. * * \note Pushing more than width * height values results in undefined * behavior. */ void push(T val); /** * \brief Calculate the sum of values in the given rectangle. * * \note If the rectangle exceeds the image area, the behaviour is * undefined. */ T sum(QRect const& rect) const;private: void init(int width, int height); T* m_pData; T* m_pCur; T* m_pAbove; T m_lineSum; int m_width; int m_height;};template<typename T>IntegralImage<T>::IntegralImage(int const width, int const height): m_lineSum() // init with 0 or with default constructor.{ // The first row and column are fake. init(width + 1, height + 1);}template<typename T>IntegralImage<T>::IntegralImage(QSize const& size): m_lineSum() // init with 0 or with default constructor.{ // The first row and column are fake. init(size.width() + 1, size.height() + 1);}template<typename T>IntegralImage<T>::~IntegralImage(){ delete[] m_pData;}template<typename T>voidIntegralImage<T>::init(int const width, int const height){ m_width = width; m_height = height; m_pData = new T[width * height]; // Initialize the first (fake) row. // As for the fake column, we initialize its elements in beginRow(). T* p = m_pData; for (int i = 0; i < width; ++i, ++p) { *p = T(); } m_pAbove = m_pData; m_pCur = m_pAbove + width; // Skip the first row.}template<typename T>voidIntegralImage<T>::push(T const val){ m_lineSum += val; *m_pCur = *m_pAbove + m_lineSum; ++m_pCur; ++m_pAbove;}template<typename T>voidIntegralImage<T>::beginRow(){ m_lineSum = T(); // Initialize and skip the fake column. *m_pCur = T(); ++m_pCur; ++m_pAbove;}template<typename T>inline TIntegralImage<T>::sum(QRect const& rect) const{ // Keep in mind that row 0 and column 0 are fake. int const pre_left = rect.left(); int const pre_right = rect.right() + 1; // QRect::right() is inclusive. int const pre_top = rect.top(); int const pre_bottom = rect.bottom() + 1; // QRect::bottom() is inclusive. T sum(m_pData[pre_bottom * m_width + pre_right]); sum -= m_pData[pre_top * m_width + pre_right]; sum += m_pData[pre_top * m_width + pre_left]; sum -= m_pData[pre_bottom * m_width + pre_left]; return sum;}
阅读全文
0 0
- 积分图的优化
- solr学习入门---积分商城基于Solr的搜索引擎优化
- 图像积分图的计算
- 积分图
- 积分图
- 积分图
- 积分图
- 积分图
- 积分图
- 积分图
- 积分图
- 自己想的积分图代码
- 积分图的概念、计算及代码
- cvIntegral—积分图的计算
- 基于积分图的均值滤波算法
- PID算法的C语言实现五 积分分离的PID优化
- PID算法的C语言实现六 抗积分饱和的PID优化
- PID算法的C语言实现七 梯形积分的PID优化
- A + B Problem II
- [Windows核心编程] 如何编写Unicode源代码
- [Windows核心编程] 谈谈Windows中的错误处理机制
- RecyclerView使用中同一个Item总是有两个viewholder对象
- Vue 爬坑之路(七)—— 监听滚动事件 实现动态锚点
- 积分图的优化
- Java排序对比
- Vue 爬坑之路(八)—— 使用 Echarts 创建图表
- java获取两个字符串日期之间间隔的天数
- 使用JSON-WEB-TOKENS方式认证用户登录
- 最常用正则表达式
- 笔记本usb2.0不可用,usb3.0正常
- [编程规范] 函数
- Failed to read schema document 'http://code.alibabatech.com/schema/dubbo/dubbo.xsd'问题解决方法