Vector


vector 复制

// 方法1
vector<int > v1(v2);//声明

// 方法2 使用swap进行交换:
vector<int > v1();
v1.swap(v2);

// 方法3 使用函数assign进行赋值 【推荐】
vector<int > v1;//声明v1
v1.assign(v2.begin(), v2.end());//将v2赋值给v1

// 方法4 循环赋值
vector<int >::iterator it;//声明迭代器
for(it = v2.begin();it!=v2.end();++it){//遍历v2,赋值给v1
     v1.push_back(it);
}

reserve 和resize

在Vector中,size是指容器当前拥有元素的个数,而capacity是指容器在必须分配新的存储空间之前可以存放的元素总数。

reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。此时size() != capacity()。 resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了 此时size() == capacity()。

vector<int> myVec, myVec1;
myVec.reserve( 100 );     // 新元素还没有构造, 此时不能用[]访问元素, 但在VS中Release模式下可以
cout << "size = " << myVec.size() << " \t capacity =" << myVec.capacity() << "endl";
for (int i = 0; i < 100; i++ )
{ 
     myVec.push_back( i ); //新元素这时才构造
}
myVec1.resize( 102 );      // 用元素的默认构造函数构造了两个新的元素
myVec1[100] = 1;           //直接操作新元素
myVec1[101] = 2;  
cout << "size = " << myVec1.size() << " \t capacity =" << myVec1.capacity() << "endl";
  • resize
     vector<int> vi={1,2,3}; 
     vi.resize(10, 9); 
     for(auto it=vi.begin();it!=vi.end();++it)  
          cout<<*it<<"  "; 
     // 输出结果为 1 2 3 9 9 9 9 9 9 9
    

#OpenCV


下面几篇blog可以参考

OpenCV for Matlab Users 2 OpenCV for Matlab Users 3 OpenCV for Matlab Users 4 OpenCV for Matlab Users 5


Mat

如果对Mat中的rows cols与height width感到迷惑,可以看看 这篇文章 简单来说 在openCV新接口中(如 Mat, Range)是先rows 后cols 在老版本的接口类型中(如Point ,Rect) 是先宽后高 (x , y, w, h)

总的来说就是: Mat类的rows(行)<==> IplImage结构体的heigh(高)<==> point.y
Mat类的cols(列) <==> IplImage结构体的width(宽)<==> point.x
``` c++ // 初始化 Mat::zeros(thinIm.rows, thinIm.cols, CV_8U); Mat depth(h, w, DataType::type, cv::Scalar::all(0)); Mat zeroMatrix(Size(w, h), CV_8UC1, Scalar(0));

// 数组 float data = new float[rowscols]; Mat mt(rows, cols, CV_32FC1, data);

//是否加载成功 if(img.empty()) return -1;

//判断是否有数据 if(!img.data) return -1;

- **Range()**
  Range是为了使opencv的使用更像Matlab而产生的。
  比如Range::all()其实就是Matlab里的符号:或者...。
  而Range(a, b)其实就是Matlab中的a:b (**包含a 不包括b**)

``` c++
// 第0行至第99行-->h, 
// 第50列至199列-->w
// 返回的是视图, 修改roi_img 依旧会改变 src_img
roi_img = src_img(Range(0,100),Range(50,200));

// Range是适用Mat类型的
// Rect是旧接口
Mat  B = A(Range::all(), Range(1, 300));
Mat  B = A(Rect(0,0,100,100));
  • Mat::setTo()

    setTo(Scalar s, mask)函数是将图像设置为某个值,第二个参数是mask,可以省略

// 将src的值全部设置成0
src.setTo(0)

// 将src中大于或者小于某个值的像素值设置为指定的值 
src.setTo(0,src < 10);
  • Mat 是否相等 来源于这个博客,点击查看原文 ``` c++ bool matIsEqual(const cv::Mat mat1, const cv::Mat mat2) { if (mat1.empty() && mat2.empty()) { return true; } if (mat1.cols != mat2.cols || mat1.rows != mat2.rows || mat1.dims != mat2.dims|| mat1.channels()!=mat2.channels()) { return false; } if (mat1.size() != mat2.size() || mat1.channels() != mat2.channels() || mat1.type() != mat2.type()) { return false; } int nrOfElements1 = mat1.total()mat1.elemSize(); if (nrOfElements1 != mat2.total()mat2.elemSize()) return false; bool lvRet = memcmp(mat1.data, mat2.data, nrOfElements1) == 0; return lvRet; }


### Rect
``` c++
// 定义
typedef Rect_<int> Rect;

Rect_(); // 形参列表为空,即定义一个空窗口(默认值为:x=y=width=height=0)

// 略过不提
Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
Rect_(const Rect_& r);
Rect_(const CvRect& r);

//org为左上角起点, sz为 (width, height)
Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);

// 由两个点构成的矩形 左上和右下
Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);

常用函数

rect.area();     //返回rect的面积 5000  
rect.size();     //返回rect的尺寸 [50 × 100]  
rect.tl();       //返回rect的左上顶点的坐标 [100, 50]  
rect.br();       //返回rect的右下顶点的坐标 [150, 150]  
rect.width();    //返回rect的宽度 50  
rect.height();   //返回rect的高度 100  
rect.contains(Point(x, y));  //返回布尔变量,判断rect是否包含Point(x, y)点  
  
//还可以求两个矩形的交集和并集  
rect = rect1 & rect2;  
rect = rect1 | rect2;  
  
//还可以对矩形进行平移和缩放    
rect = rect + Point(-100, 100); //平移,也就是左上顶点的x坐标-100,y坐标+100  
rect = rect + Size(-100, 100);  //缩放,左上顶点不变,宽度-100,高度+100  
  
//还可以对矩形进行对比,返回布尔变量  
rect1 == rect2;  
rect1 != rect2;  

cvtColor 颜色空间转换

cv::cvtColor(srcImage, dstImage, cv::COLOR_GRAY2BGR);
cv::cvtColor(srcImage, dstImage, cv::COLOR_BGR2GRAY);

convertTo 类型转换

src.convertTo(dst, type, scale, shift)

 dst(i) = (type) scale* src(i) +shift
using namespace cv;

Mat mat, mat1;
mat = Mat::zeros(100,100,CV_32F);   // 得到一个浮点型的100*100的矩阵  
mat.convertTo(mat1, CV_8U); 		// 把矩阵mat转为unsing char类型的矩阵

转换为浮点数需要加上scale,否则imshow显示的时候会全白 for example, 255 becomes 255.0. But when you try `imshow’ the resulting image, the command expects all pixel values to be between 0.0 and 1.0.

mat.convertTo(output, CV_32F, 1.0/255.0)

findNonZero

Mat Im, NonZeroLoc;
findNonZero(Im, NonZeroLoc);
for (int i = 0; i < NonZeroLoc.total(); i++) {
	x = NonZeroLoc.at<Point>(i).x;					// w  即cols
	y = NonZeroLoc.at<Point>(i).y;					// h  即rows
}

得到的NonZeroLoc的遍历结果,顺序是先高后宽,可以想象成一条竖线由左向右移动,竖线上的点由上而下。

Matlab find

//Matlab: B(A<1)=0 
Mat B= A > 1;

// src2= (src1 <220 & src3 > 100); 	// Error, 条件不能是两个变量,即使大小相同  
src2= (src1 <220 & src1 > 100);		// 可以通过  
  • compare函数

void compare(InputArray src1, InputArray src2, OutputArray dst, int cmpop);

src1:原始图像1(必须是单通道)或者一个数值,比如是一个Mat或者一个单纯的数字n; src2:原始图像2(必须是单通道)或者一个数值,比如是一个Mat或者一个单纯的数字n; dst:结果图像,类型是CV_8UC1,即单通道8位图,大小和src1和src2中最大的那个一样,比较结果为真的地方值为 255,否则为0; cmpop:操作类型,有以下几种类型: enum { CMP_EQ=0, //相等
CMP_GT=1, //大于
CMP_GE=2, //大于等于
CMP_LT=3, //小于
CMP_LE=4, //小于等于
CMP_NE=5 //不相等 };

// 从图像中找出像素值为50的像素点
cv::Mat result;  
cv::compare(image,50, result, cv::CMP_EQ);  

OpenCV 常用封装函数

void putTextonIm(Mat& mask, string text, Scalar color=Scalar(255, 0, 0))
{
	int font_face = cv::FONT_HERSHEY_COMPLEX;
	double font_scale = 2;
	int thickness = 2;
	int baseline;
	//获取文本框的长宽  
	cv::Size text_size = cv::getTextSize(text, font_face, font_scale, thickness, &baseline);
	cv::Point origin;
	origin.x = mask.cols / 2 - text_size.width / 2;
	origin.y = mask.rows / 2 + text_size.height / 2;
	cv::putText(mask, text, origin, font_face, font_scale, color, thickness, 8, 0);
}

Class && 符号重载

实现 begin() 和 end() 可以进行for循环遍历

class MyClass
{  
public:  
    MyClass():a{ 1,2,3,4,5 }   
    {  
    }  
  
    int* begin()//stl::begin模版调用  
    {   
        return a;  
    }   
  
    int* end() //stl::end模版可以调用  
    {   
        return a + sizeof(a)/sizeof(int);  
    } 
	
	// 重载[]操作符,作为右值
	int& operator [](const int index);
	const int& operator [](const int index) const;
private:  
    int a[5];  
}; 

int main()
{
	MyClass myclass;
	for(int var : myclass)  
        cout << var << " ";  
	
	for(int i=0 ; i < 5; ++i)
		cout << myclass[i] << " "; 
}

常用函数

// 数字转字符串
string str = std::to_string(42);
// 字符串分割函数  
std::vector<std::string> split(std::string str,std::string pattern)  
{  
    std::string::size_type pos;  
    std::vector<std::string> result;  
    str+=pattern;//扩展字符串以方便操作  
    int size=str.size();  
  
    for(int i=0; i<size; i++)  
    {  
        pos=str.find(pattern,i);  
        if(pos<size)  
        {  
            std::string s=str.substr(i,pos-i);  
            result.push_back(s);  
            i=pos+pattern.size()-1;  
        }  
    }  
    return result;  
}  

min/max宏冲突

Windows.h中的 max min会和 std::max std::min冲突 解决方法有下面两个

  1. 项目属性 ——> C/C++ ——> 预处理器 ——> 预处理器定义 ——>加入NOMINMAX

  2. 加上下面预处理代码

     #define NOMINMAX
     #undef max
     #undef min