看到的一些代码,看到不少陌生的函数。记录一点之前没怎么用过的c++的用法。
explicit operator bool() const { return state; }
int operator()(const cv::Mat &image);
显式的类型转换运算符(explicit)

为了防止四中的异常情况发生,C++11标准引入了显式的类型转换运算符explicit
显示转换之后,不能直接使用隐式规则对类进行类型转换,需要使用static_cast显式的对类进行转换
格式:通过explicit关键字定义
class SmallInt {
private:
std::size_t val;
public:
SmallInt(int i = 0) :val(i) {
if (i < 0 || i>255)
throw std::out_of_range("Bad SmallInt value");
}
operator int()const { return val; }
};

SmallInt si;
si = 4; //首先将4隐式转换为SmallInt,然后调用SmallInt::operator=
cout << si + 3 << endl; //打印7。首先将si隐式地转换为int,然后执行整数的加法。如果不定义operator,那么这一步将出错

struct A {
A() = default;
A(const B&); //把一个B转换成A
};

struct B {
operator A()const; //也是把一个B转换成A
}

fmax()函数是cmath标头的库函数,用于查找给定数字的最大值,它接受两个数字并返回较大的一个。

Syntax of fmax() function:

fmax()函数的语法:

fmax(x, y);

RotatedRect该类表示平面上的旋转矩形,有三个属性:

矩形中心点(质心)
边长(长和宽)
旋转角度
class CV_EXPORTS RotatedRect
{
public:
//构造函数
RotatedRect();
RotatedRect(const Point2f& center, const Size2f& size, float angle);
RotatedRect(const CvBox2D& box);
void points(Point2f pts[]) const;//!返回矩形的4个顶点
Rect boundingRect() const; //返回包含旋转矩形的最小矩形
operator CvBox2D() const; //!转换到旧式的cvbox2d结构
Point2f center; //矩形的质心
Size2f size; //矩形的边长
float angle; //旋转角度,当角度为0、90、180、270等时,矩形就成了一个直立的矩形
};
std::vector<cv::Mat> channels;       // 通道拆分

cv::split(src, channels); /************************/
if (enemy_color == ENEMY_BLUE) { /* */
color_channel = channels[0]; /* 根据目标颜色进行通道提取 */
} else if (enemy_color == ENEMY_RED) { /* */
color_channel = channels[2]; /************************/
}

int light_threshold;
if(enemy_color == ENEMY_BLUE){
light_threshold = 225;
}else{
light_threshold = 200;
}

常使用push_back()向容器中加入一个右值元素(临时对象)时,首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放入容器中。原来的临时变量释放。这样造成的问题就是临时变量申请资源的浪费。
引入了右值引用,转移构造函数后,push_back()右值时就会调用构造函数和转移构造函数,如果可以在插入的时候直接构造,就只需要构造一次即可。这就是c++11 新加的emplace_back
void cv::split(
const cv::Mat& mtx, //输入图像
vector& mv // 输出的多通道序列(n个单通道序列)
);

cv::Mat src = imread("lenna.jpg", cv::IMREAD_COLOR);
cv::imshow("src", src);

// Split the image into different channels
std::vector<cv::Mat> rgbChannels(3);
split(src, rgbChannels);

// Show individual channels
cv::Mat blank_ch, fin_img;
blank_ch = cv::Mat::zeros(cv::Size(src.cols, src.rows), CV_8UC1);

// Showing Red Channel
// G and B channels are kept as zero matrix for visual perception
std::vector<cv::Mat> channels_r;
channels_r.push_back(blank_ch);
channels_r.push_back(blank_ch);
channels_r.push_back(rgbChannels[2]);

/// Merge the three channels
cv::merge(channels_r, fin_img);
cv::imshow("R", fin_img);


// Showing Green Channel
std::vector<cv::Mat> channels_g;
channels_g.push_back(blank_ch);
channels_g.push_back(rgbChannels[1]);
channels_g.push_back(blank_ch);
cv::merge(channels_g, fin_img);
cv::imshow("G", fin_img);

opencv imdecode和imencode用法

主要是对内存数据自动编解码

string fname = "D:/image.jpg";
//! 以二进制流方式读取图片到内存
FILE* pFile = fopen(fname.c_str(), "rb");
fseek(pFile, 0, SEEK_END);
long lSize = ftell(pFile);
rewind(pFile);
char* pData = new char[lSize];
fread(pData, sizeof(char), lSize, pFile);
fclose(pFile);

//! 解码内存数据,变成cv::Mat数据
cv::Mat img_decode;
vector<uchar> data;
for (int i = 0; i < lSize; ++i){
data.push_back(pData[i]);
}
img_decode = cv::imdecode(data, CV_LOAD_IMAGE_COLOR);

程序首先读入一个图片。然后encode,之后把encode后的内容写入文件(实际应用可以发送到网络)。
第二步,从文件读取encode的内容。然后解码decode。转换为mat格式,显示出来。

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <iostream>
#include <sstream>
#include <string>
#include <opencv2/opencv.hpp>
#include <vector>

using namespace boost::filesystem;
namespace newfs = boost::filesystem;
using namespace cv;
————————————————

int main(int argc, char ** argv)
{
cv::Mat img_encode;
img_encode = imread("../res/test.png", CV_LOAD_IMAGE_COLOR);

//encode image and save to file
std::vector<uchar> data_encode;
imencode(".png", img_encode, data_encode);
std::string str_encode(data_encode.begin(), data_encode.end());

path p("../res/imgencode_cplus.txt");
newfs::ofstream ofs(p);
assert(ofs.is_open());
ofs << str_encode;
ofs.flush();
ofs.close();

//read image encode file and display
newfs::fstream ifs(p);
assert(ifs.is_open());
std::stringstream sstr;
while(ifs >> sstr.rdbuf());
ifs.close();

Mat img_decode;
std::string str_tmp = sstr.str();
std::vector<uchar> data(str_tmp.begin(), str_tmp.end());
img_decode = imdecode(data, CV_LOAD_IMAGE_COLOR);
imshow("pic",img_decode);
cvWaitKey(10000);

return 0;
————————————————

imencode(".png", img_encode, data_encode); 第一个参数是图片后缀,第二个:Mat类型,第三个:vector类型 应该意为把Mat编码为向量。
注意两个函数的参数数量。imdecode有两个参数,encode有三个
注意这个写法:
std::vector data(str_tmp.begin(), str_tmp.end()); 直接把字符串转化为一组unchar类型的向量。

相机标定部分:

//
// StereoCalib.h
// stereo_calibrate_toe
//
// Created by ding on 17/8/17.
// Copyright (c) 2017年 ding. All rights reserved.
//

#ifndef __stereo_calibrate_toe__StereoCalib__
#define __stereo_calibrate_toe__StereoCalib__

#include "Header.h"

typedef struct{
int height;
int width;
float distance_const;
float f;
//float yparam_const;
//float ground;
//float init_z;
float lightbase;
}CalibParam;

class StereoCalib{
public:
StereoCalib(const string &path){
filehead = path;
this->zpos = 0;
this->ypos = 0;
this->xpos = 0;
};
void KeyParam(int key);
void Process(Mat &left,Mat &right);
private:
void distanceCalib();
void X_calib();
void Y_calib();
void FindTarget();
void Position_show();
void center_g(const vector<Point> contour,Point ¢er);
void OtherOption();
public:
Mat thresleft_cp,thresright_cp;
private:
int rows,cols;
int key;
int calib_process = 0;
int VisionDis = 0;
vector<vector<Point> > contours_left,contours_right,Triangle_left,Triangle_right;
vector<Vec4i> hierarchy_L,hierarchy_R;
vector<Point> approx_left,approx_right;
Point left_center,right_center;
vector<Mat> split_left,split_right;
Mat left_diff[2],right_diff[2];
Mat init_left,init_right;
int first_dis,second_dis;
float xpos,ypos,zpos;
float x_cal_z,x_cal_x1,x_cal_x2;
Mat thresleft,thresright;
int first_y,y_cal_z;
double tan_theta;
CalibParam Param;
string filehead;
};



#endif /* defined(__stereo_calibrate_toe__StereoCalib__) */

cpp:

#include "StereoCalib.h"

void StereoCalib::Process(Mat &left,Mat &right){
init_left = left;
init_right = right;
Triangle_left.clear();
Triangle_right.clear();
split(left,split_left);
split(right, split_right);
left_diff[0] = split_left[2] - split_left[1];
right_diff[0] = split_right[2] - split_right[1];
left_diff[1] = split_left[0] - split_left[1];
right_diff[1] = split_right[0] - split_right[1];
int total = right_diff[0].rows*right_diff[0].cols;
rows = right_diff[0].rows;
cols = right_diff[1].cols;
thresleft = left_diff[0] + left_diff[1];
thresright = right_diff[0] + right_diff[1];
threshold(thresleft,thresleft,0,255,THRESH_OTSU);
threshold(thresright,thresright,0,255,THRESH_OTSU);
thresleft_cp = thresleft.clone();
thresright_cp = thresright.clone();
findContours(thresleft, contours_left,hierarchy_L,CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
findContours(thresright, contours_right,hierarchy_R,CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
int tlsize = 0;
for(int i=0;i<contours_left.size();i++){
approxPolyDP(contours_left[i], approx_left, 10, true);
if(approx_left.size() == 4 && hierarchy_L[i][2] == -1 && hierarchy_L[i][3] != -1){
contourArea(contours_left[i]);
if(contourArea(contours_left[i]) > tlsize){
tlsize = contourArea(contours_left[i]);
Triangle_left.clear();
center_g(contours_left[i], left_center);
//circle(left, left_center, 5, Scalar(0,0,0),-1);
Triangle_left.push_back(contours_left[i]);
}
}
}
for(int i=0;i<Triangle_left.size();i++){\
if(tlsize==contourArea(Triangle_left[i])){
center_g(Triangle_left[i], left_center);
}
}
circle(left, left_center, 5, Scalar(0,0,0),-1);
int trsize = 0;
for(int i=0;i<contours_right.size();i++){
approxPolyDP(contours_right[i], approx_right, 10, true);
if(approx_right.size() == 4 && hierarchy_R[i][2] == -1 && hierarchy_R[i][3] != -1){
contourArea(contours_right[i]);
if(contourArea(contours_right[i]) > trsize){
trsize = contourArea(contours_right[i]);
Triangle_right.clear();
center_g(contours_right[i], right_center);
Triangle_right.push_back(contours_right[i]);
}
}
}
for(int i=0;i<Triangle_right.size();i++){\
if(trsize==contourArea(Triangle_right[i])){
center_g(Triangle_right[i], right_center);
}
}
circle(right, right_center, 5, Scalar(0,0,0),-1);
drawContours(left, Triangle_left, -1, Scalar(255,0,0),3);
drawContours(right, Triangle_right, -1, Scalar(255,0,0),3);
if(Triangle_left.size() == 1 && Triangle_right.size() == 1) VisionDis = abs(left_center.x - right_center.x);
distanceCalib();
X_calib();
Y_calib();
Position_show();
OtherOption();
}

void StereoCalib::KeyParam(int key){
this->key = key;
}

void StereoCalib::Position_show(){
if(calib_process > 1 && VisionDis != 0){
zpos = Param.distance_const/VisionDis;
}
if(calib_process > 3 && zpos > 0 && Param.f != 0){
xpos = (left_center.x-cols/2)*zpos/Param.f;
}
if(calib_process > 5 && zpos > 0 && Param.f != 0){
ypos = (Param.lightbase- left_center.y)*zpos/Param.f;
}
ostringstream strx,stry,strz;
strx<<"x:"<<xpos<<"mm";
stry<<"y:"<<ypos<<"mm";
strz<<"z:"<<zpos<<"mm";
putText(init_left, strx.str(), Point(cols-180,rows-100),FONT_HERSHEY_COMPLEX , 1, Scalar(255,0,255));
putText(init_left, stry.str(), Point(cols-180,rows-70),FONT_HERSHEY_COMPLEX , 1, Scalar(255,0,255));
putText(init_left, strz.str(), Point(cols-180,rows-40),FONT_HERSHEY_COMPLEX, 1, Scalar(255,0,255));
}

void StereoCalib::distanceCalib(){
if(calib_process == 0){
putText(init_left, "Press 'd' for 1st position.", Point(100,50), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255,0,255));
if(key == 'd'){
first_dis = VisionDis;
Param.height = rows;
Param.width = cols;
calib_process = 1;
std::cout<<"Move away 10.0cm,then press 'x'."<<std::endl;
}

}
if(calib_process == 1){
putText(init_left,"Move away 10.0cm,then press 'x'.", Point(100,50), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255,0,255));
if(key == 'x'){
second_dis = VisionDis;
Param.distance_const = 100.0*((float)(first_dis * second_dis))/((float)(first_dis - second_dis));
calib_process = 2;
std::cout<<"Stay and press 'd'."<<std::endl;
}
}
}

void StereoCalib::X_calib(){
if(calib_process == 2){
putText(init_left, "Stay and press 'd'.", Point(100,50), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255,0,255));
if(key == 'd'){
x_cal_z = zpos;
x_cal_x1 = left_center.x;
calib_process = 3;
std::cout<<"Move right 10cm,then press 'x'."<<std::endl;
}
}
if(calib_process == 3){
putText(init_left, "Move right 10cm,then press 'x'.", Point(100,50), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255,0,255));
if(key == 'x'){
x_cal_x2 = left_center.x;
Param.f = (x_cal_x2 -x_cal_x1) * x_cal_z / 100.0;
calib_process = 4;
std::cout<<"Move to first z.Stay and press 'd'."<<std::endl;
}
}
}

void StereoCalib::Y_calib(){
if(calib_process == 4){
putText(init_left, "Move to first z.Stay and press 'd'.", Point(100,50), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255,0,255));
if(key == 'd'){
first_y = left_center.y;
y_cal_z = zpos;
calib_process = 5;
std::cout<<"Move to second z.Stay and press 'x'."<<std::endl;
}
}
if(calib_process == 5){
putText(init_left, "Move to second z.Stay and press 'x'.", Point(100,50), FONT_HERSHEY_COMPLEX_SMALL, 1, Scalar(255,0,255));
if(key == 'x'){
Param.lightbase = (first_y * y_cal_z - left_center.y * zpos) / (y_cal_z - zpos);
calib_process = 6;
std::cout<<"finish"<<std::endl;
}
}
}


void StereoCalib::OtherOption(){
if(calib_process == 6){
filehead.append("stereo_calib.xml");
FileStorage fs(filehead,FileStorage::WRITE);
fs<<"height"<<Param.height
<<"width"<<Param.width
<<"distance_const"<<Param.distance_const
<<"f"<<Param.f
<<"lightbase"<<Param.lightbase;
fs.release();
calib_process = 7;
}
}

void StereoCalib::center_g(const vector<Point> contour,Point ¢er){
Moments mu; // Get the center of a contour
mu = moments(contour,false);
center.x=mu.m10/mu.m00;
center.y=mu.m01/mu.m00;
}