open cv+C++错误及经验总结(二)

来源:互联网 发布:sql数据库修复 编辑:程序博客网 时间:2024/06/05 23:04
 


颜色缩减方法:

如果矩阵元素存储的是单通道像素,使用C或C++的无符号字符类型,那么像素可有256个不同值。但若是三通道图像,这种存储格式的颜色数就太多了(确切地说,有一千六百多万种)。用如此之多的颜色可能会对我们的算法性能造成严重影响。其实有时候,仅用这些颜色的一小部分,就足以达到同样效果。

这种情况下,常用的一种方法是 颜色空间缩减 。其做法是:将现有颜色空间值除以某个输入值,以获得较少的颜色数。例如,颜色值0到9可取为新值0,10到19可取为10,以此类推。

uchar (无符号字符,即0到255之间取值的数)类型的值除以 int 值,结果仍是 char 。因为结果是char类型的,所以求出来小数也要向下取整。利用这一点,刚才提到在uchar 定义域中进行的颜色缩减运算就可以表达为下列形式:

I_{new} = (\frac{I_{old}}{10}) * 10

这样的话,简单的颜色空间缩减算法就可由下面两步组成:一、遍历图像矩阵的每一个像素;二、对像素应用上述公式。值得注意的是,我们这里用到了除法和乘法运算,而这两种运算又特别费时,所以,我们应尽可能用代价较低的加、减、赋值等运算替换它们。此外,还应注意到,上述运算的输入仅能在某个有限范围内取值,如uchar 类型可取256个值。

对于较大的图像,有效的方法是预先计算所有可能的值,然后需要这些值的时候,利用查找表直接赋值即可。(查找表可以是一维或多维数组,存储不同输入值所对应的输出值,优势在于只需读取,无需计算。)

make sense of 有道理  

in case of  万一,防备

iterator 迭代器  index 索引,指示,标志 indices(index复数)

successive连续的  sake缘故,理由

random-access随机存取的 serial 连续的,串行

Some operations, like the one above, do not actually depend on the array shape. They just process elements of an array one by one (or elements from multiple arrays that have the same coordinates, for example, array addition). Such operations are called element-wise. It makes sense to check whether all the input/output arrays are continuous, namely, have no gaps at the end of each row. If yes, process them as a long single row:

// compute the sum of positive matrix elements, optimized variantdouble sum=0;int cols = M.cols, rows = M.rows;if(M.isContinuous()){    cols *= rows;    rows = 1;}for(int i = 0; i < rows; i++){    const double* Mi = M.ptr<double>(i);    for(int j = 0; j < cols; j++)        sum += std::max(Mi[j], 0.);}

In case of the continuous matrix, the outer loop body is executed just once. So, the overhead is smaller, which is especially noticeable in case of small matrices.

Finally, there are STL-style iterators that are smart enough to skip gaps between successive rows:

// compute sum of positive matrix elements, iterator-based variantdouble sum=0;MatConstIterator_<double> it = M.begin<double>(), it_end = M.end<double>();for(; it != it_end; ++it)    sum += std::max(*it, 0.);

 

2.使用addweighted()函数将两图像叠加  scalar梯状的,分等级的

C++: void addWeight(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1)

Parameters

src1-Fisrt source array.

alpha-Weight for the first array elements.

src2-Second source array of the same size and channel number as src1.

beta-Weight for the second array elements.

dst-Destination array that has the same size and number of channels as the input arrays.

gamma-Scalar added to each sum.

dtype-optional depth of the destination array.when both input arrays have the same depth, dtype can be set to -1, which will be equivalent to src1.depth().

 

The function addWeighted calculates the weighted sum of two arrays as follows:

dst(1) = saturate(src1(1)alpha + src2(1)beta + gamma)

where I is a multi-dimensional index of array elements.In case of multi-channel arrays, each channel is processed independently.

The function can be replaced with a matrix expression:

dst = src1 * alpha + src2 * beta + gamma;
C++: void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray
dst, int dtype=-1)void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray
dst, int dtype=-1)void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray
dst, int dtype=-1)

#include "stdafx.h"#include"cv.h"#include"highgui.h"using namespace cv;using namespace std;void blending_test(){Mat src1, src2, dst;double alpha = 0.4;double beta = 1-alpha;src1 = imread("F:/HU/test_image/Airplane.jpg",CV_LOAD_IMAGE_COLOR);src2 = imread("F:/HU/test_image/Airplane.jpg",CV_LOAD_IMAGE_COLOR);if(!src1.data) cout<<"error loading src1"<<endl;if(!src2.data) cout<<"error loading src2"<<endl;addWeighted(src1, alpha, src2, beta, 0.0,dst);/*cvNamedWindow("add", CV_WINDOW_AUTOSIZE);cvShowImage("add", dst);*/namedWindow("add", 1);imshow("add", dst);cvWaitKey(0);}int _tmain(int argc, _TCHAR* argv[]){blending_test();return 0;}

3.在opencv 学习中经常看见saturate_cast的使用,加入了溢出保护

02.for (int i=0; i<src1.rows; i++)  03.{  04.    const uchar* src1_ptr = src1.ptr<uchar>(i);  05.    const uchar* src2_ptr = src2.ptr<uchar>(i);  06.    uchar* dst_ptr  = dst.ptr<uchar>(i);  07.    for (int j=0; j<src1.cols*nChannels; j++)  08.    {  09.        dst_ptr[j] = saturate_cast<uchar>(src1_ptr[j]*alpha + src2_ptr[j]*beta + gama);//gama = -100, alpha = beta = 0.5  10.//      dst_ptr[j] = (src1_ptr[j]*alpha + src2_ptr[j]*beta + gama);  11.    }  12.}  13.imshow("output2",dst);  


 


 

0 0