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);
}
内存释放
vector内存释放需要使用下面语句
单独的clear会导致内存泄漏
vector<T>().swap(x);
x.clear();
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
// 初始化
Mat::zeros(thinIm.rows, thinIm.cols, CV_8U);
Mat depth(h, w, DataType<ushort>::type, cv::Scalar::all(0));
Mat zeroMatrix(Size(w, h), CV_8UC1, Scalar(0));
// 数组
float *data = new float[rows*cols];
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)
// 第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 是否相等
来源于这个博客,点击查看原文
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
// 定义
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);
将多 channels转成1 channels
static Mat formatImageForPCA(const Mat &data, int rows)
{
Mat dst(rows, 2, CV_32F);
for (unsigned int i = 0; i < rows; i++)
{
Mat image_row = data.row(i).clone().reshape(1, 1);
Mat row_i = dst.row(i);
image_row.convertTo(row_i, CV_32F);
}
return dst;
}
Mat::type
Mat::type() 表示了矩阵中元素的类型以及矩阵的通道个数
Mat a(n, n, src.type(), ptr, astep);
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;
}
std::next_permutation
C++的全排列函数
min/max宏冲突
Windows.h中的 max min会和 std::max std::min冲突
解决方法有下面两个
项目属性 ——> C/C++ ——> 预处理器 ——> 预处理器定义 ——>加入NOMINMAX
加上下面预处理代码
#define NOMINMAX #undef max #undef min