0. 重点网站

  1. middlebury 数据下载: https://vision.middlebury.edu/stereo/submit3/

一. 基本操作

作用: 复现论文中的公式的时候会应用到。

1. 使用exp

#include <cmath>        // std::exp(double)

http://www.cplusplus.com/reference/valarray/exp/

2. 平方/次方

注意,不是^, 不是 ^, 不是 ^.
是pow, 是pow, 是pow。

template<class T> valarray<T> pow (const valarray<T>& x, const valarray<T>& y);
template<class T> valarray<T> pow (const valarray<T>& x, const T& y);
template<class T> valarray<T> pow (const T& x, const valarray<T>& y);

3. 将视差图写入txt

FileStorage fs(writeTxtPath, FileStorage::WRITE);
fs << dst;
fs.release();

4. 程序运行时间计算

#include<ctime>
clock_t start;
clock_t end1;
start = clock();
end1 = clock();
double endtime = (double)(end1 - start) / CLOCKS_PER_SEC;
cout << "Total time:" << endtime << endl;		//s为单位
cout << "Total time:" << endtime * 1000 << "ms" << endl;	//ms为单位

方法2:

#include <chrono>

chrono::steady_clock::time_point t1, t2;
chrono::duration<double> time_used;

t1 = chrono::steady_clock::now();  // 计时
t2 = chrono::steady_clock::now();
time_used = chrono::duration_cast <chrono::duration < double >> (t2 - t1);

二. opencv mat操作


作用: 影像就是矩阵,对于矩阵的操作不可避免。


1. BGR转YUV并分割三通道

//inImage为输入的RGB图像
	cv::Mat imageY(inImage.rows,inImage.cols,1);
	cv::Mat imageU(inImage.rows,inImage.cols,1);
	cv::Mat imageV(inImage.rows,inImage.cols,1);	
	
	cv::Mat imageYUV;
	cv::cvtColor(inImage,imageYUV,CV_BGR2YUV);
	std::vector<Mat> mv;
	split(inImage, (vector<Mat>&)mv);
 
	imageY = mv[0].clone();
	imageU = mv[1].clone();
	imageV = mv[2].clone();

2. 彩色图转灰度图

	Mat my_bgr = imread(...);// 读自己的影像  
	Mat my_grey;
	cv::cvtColor(my_bgr, my_grey, cv::COLOR_BGR2GRAY);

3. 生成全0,全1矩阵

Mat tmpdata0 = Mat::zeros(rows, cols, CV_8UC1);//rows行cols列的全0矩阵
Mat tmpdata1 = Mat::ones(rows, cols, CV_8UC1);//rows行cols列的全0矩阵
// 应用之一:将mat中所有的数值初始化为一个特定的值,比如72
Mat tmpdata72 = 72* Mat::ones(rows, cols, CV_8UC1);

4. 取值

- 浮点取值(i,j处):
float* ptr_Affinity = Affinity_matrix.ptr<float>(i);
ptr_Affinity[j]

- uchar取值(i,j处):
uchar* ptr_Affinity = Affinity_matrix.ptr<uchar>(i);
ptr_Affinity[j]

5. 取矩阵的roi

int x=280; // 裁剪区域起始点 x坐标
int y=400; // 裁剪区域起始点 y坐标
int width=100; // 裁剪区域宽度
int height=100; // 裁剪区域高度

Rect area(x, y, width, height);
Mat guide_roi = guide(area);

读取txt, 转为浮点型的mat

void txt2Mat32F(fstream &txtfile, int rows, int cols, Mat &target) {
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			txtfile >> target.at<float>(i, j);
		}
	}
	return;
}

视差后处理的opencv函数

https://docs.opencv.org/master/da/d17/group__ximgproc__filters.html

1. DT滤波 (domain filter)

头文件:

#include <opencv2/ximgproc/edge_filter.hpp>

调用示例:

    double sigmaSpatial = 0.2;
    double sigmaColor = 0.1;
    cv::Ptr<cv::ximgproc::DTFilter> dtf = cv::ximgproc::createDTFilter(guideImg, sigmaSpatial, sigmaColor, cv::ximgproc::DTF_NC,3);
    dtf->filter(src, dst, -1);
    //cv::ximgproc::dtFilter(guideImg, src, dst, sigmaSpatial, sigmaColor, cv::ximgproc::DTF_NC, 3);
    cv::namedWindow("Domain Transform Filter");
    imshow("Domain Transform Filter", dst);
    waitKey(0);
}

膨胀

	Mat structure_element = getStructuringElement(MORPH_RECT, Size(3, 3)); //设置膨胀/腐蚀的核为矩形,大小为3*3
	dilate(target_roi, target_roi_dilate, structure_element); //膨胀

三、 Eigen矩阵操作

1. elemen-wise 操作:

https://eigen.tuxfamily.org/dox/group__TutorialArrayClass.html

2. L2范数计算

VectorXf v(2);
  v << -1,
       2;
cout << "v.squaredNorm() = " << v.squaredNorm() << endl;
cout << "v.norm() = " << v.norm() << endl;

结果:

v.squaredNorm() = 5
v.norm() = 2.23607

https://www.cnblogs.com/houkai/p/6351609.html

四、立体匹配中自用的一些小函数以及代码技巧

1. 计算最小值与次小值的比值

作用: 应用在匹配后处理的步骤中,需要最小代价与次小代价拉开一定距离才能够认为说求取的最小代价是比较准确的。

函数实现如下,需要的话,直接拷贝去就可以了。

double calSignifiRatio(vector<double> output_y){
	vector<double>::iterator smallest = min_element(begin(output_y), end(output_y));
	int position = distance(begin(output_y), smallest);
	float smallestScost, secondSmallScost, signifiRatio;
	smallestScost = output_y[position];

	//删除掉outputy中的最小值,再求其最小值即为次小值
	output_y.erase(smallest);
	vector<double>::iterator secondSmallest = min_element(begin(output_y), end(output_y));
	int secondPosition = distance(begin(output_y), secondSmallest);
	secondSmallScost = output_y[secondPosition];
	signifiRatio = secondSmallScost / smallestScost;

	return signifiRatio;
}

调用:

#include <iostream>
#include <vector>
#include <algorithm>
//#include <iterator>     // std::distance
using namespace std;
int main(){
	vector<double> output_y;
	output_y.push_back(19);
	output_y.push_back(1);
	output_y.push_back(9);
	output_y.push_back(5456);
	output_y.push_back(546);
	double ratio = calSignifiRatio(output_y); // ratio = 9
	return 0;
}

写函数之前测试的代码,也放进来好了,万一之后会用到呢。

#include <iostream>
#include <vector>
#include <algorithm>
//#include <iterator>     // std::distance
using namespace std;
int main(){
	vector<double> output_y;
	output_y.push_back(19);
	output_y.push_back(1);
	output_y.push_back(9);
	output_y.push_back(5456);
	output_y.push_back(546);
	vector<double>::iterator smallest = min_element(begin(output_y), end(output_y));
	int position = distance(begin(output_y), smallest);
	float smallestScost, secondSmallScost, signifiRatio; // 定义最小Scost值以及次小Cost值,以及其比值signifiRatio
	smallestScost = output_y[position]; //暂时定义最小值
	cout << "最小值是:" << smallestScost<< endl;

	//删除掉outputy中的最小值,再求其最小值即为次小值
	output_y.erase(smallest);

	vector<double>::iterator secondSmallest = min_element(begin(output_y), end(output_y));
	int secondPosition = distance(begin(output_y), secondSmallest);
	secondSmallScost = output_y[secondPosition];
	cout << "次小值是:" << secondSmallScost<<endl;
	signifiRatio = secondSmallScost / smallestScost;
	cout << "最小值与次小值的比值是:"<<signifiRatio << endl;
	return 0;
}

2. 抽稀视差图

def getGTsampleAndConfidence(GT, delete_percent_perDim):
    shape = GT.shape
    rows = shape[0]  # height(rows) of image
    cols = shape[1]  # width(colums) of image
    rows_vector=np.arange(0,rows)
    cols_vector=np.arange(0,cols)
    random.shuffle(rows_vector)
    gt_thin_out=GT
    for i in rows_vector:
        random.shuffle(cols_vector)
        new_cols_vector = cols_vector[0:math.floor(cols * delete_percent_perDim)]
        gt_thin_out[i,new_cols_vector]=0
    return gt_thin_out,confidence

调用:

    disp_thinout, confidence_disp = getGTsampleAndConfidence(disp, 0.99)

C++,注意uchar就用uchar的指针,float就用float的指针,切记观察输入数据的类型。

void PreProcessing::thinoutGT(const Mat &GT, float delete_percent_perDim, Mat &GT_thinout) {
	int rows = GT.rows;
	int cols = GT.cols;
	int new_rows = int(rows * delete_percent_perDim);
	int new_cols = int(cols * delete_percent_perDim);

	// 1. 构建[0,row-1]以及[0,cols-1]的两个向量
	vector<int> index_cols;
	vector<int> index_rows;

	for (int i = 0; i < rows;++i) index_rows.push_back(i);


	for (int j = 0; j < cols;++j) index_cols.push_back(j);
	random_shuffle(index_cols.begin(), index_cols.end());
	// https://blog.csdn.net/md521/article/details/8571675?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.opensearch_close&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.opensearch_close


	// https://blog.csdn.net/iv__vi/article/details/79806683
	for (auto i : index_rows) {
		uchar *ptr = GT_thinout.ptr<uchar>(i);
		random_shuffle(index_cols.begin(), index_cols.end());
		std::vector<int>::const_iterator first1 = index_cols.begin();
		std::vector<int>::const_iterator last1 = index_cols.begin() + int(delete_percent_perDim*cols); // vector 截断 https://blog.csdn.net/l1216766050/article/details/85098382
		std::vector<int> cut_index_cols(first1, last1);
		for (auto j : cut_index_cols) {
			ptr[j] = 0;
		}
	}

}

3. python sgbm调用

import numpy as np
import cv2
from matplotlib import pyplot as plt

imgL = cv2.imread('../data/stereo/im0.png')
imgR = cv2.imread('../data/stereo/im1.png')

# disparity range tuning
window_size = 9
min_disp = 0
num_disp = 360 - min_disp

stereo = cv2.StereoSGBM_create(
    minDisparity=0,
    numDisparities=256,  # max_disp has to be dividable by 16 f. E. HH 192, 256
    blockSize=7,
    P1=8 * 3 * window_size ** 2,
    # wsize default 3; 5; 7 for SGBM reduced size image; 15 for SGBM full size image (1300px and above); 5 Works nicely
    P2=32 * 3 * window_size ** 2,
    disp12MaxDiff=1,
    uniquenessRatio=15,
    speckleWindowSize=0,
    speckleRange=2,
    preFilterCap=63,
    mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY
)
disparity = stereo.compute(imgL, imgR).astype(np.float32) / 16.0
cv2.imwrite('target_piano_sgbm.png',disparity)
plt.imshow(disparity, 'gray')
plt.show()

4. C++ sgbm调用

五、开发技巧

1. 编译是否使用C++ 11

C++03:__cplusplus = 199711L
C++11:__cplusplus = 201103L
编译是否使用C++11,可以进行如下定义:
#if __cplusplus < 201103L
       #error “Should use –std=c++11 option for compile
#endif

https://blog.csdn.net/yzhang6_10/article/details/81323605

2. OpenMP

开启omp支持的步骤为“项目属性 -> C/C++ -> 所有选项 -> openmp支持 -> 是(/openmp)”。
常见错误:
https://docs.microsoft.com/zh-cn/cpp/error-messages/compiler-errors-2/compiler-error-c3031?view=vs-2019

#pragma omp parallel for

3. IDE技巧(visual studio)!!!好用

https://devblogs.microsoft.com/cppblog/c-code-editing-and-navigation-in-visual-studio/

Logo

汇聚原天河团队并行计算工程师、中科院计算所专家以及头部AI名企HPC专家,助力解决“卡脖子”问题

更多推荐