这是我第一次在StackOverflow上发布问题。我正在编写一段C++代码,试图解决半全局匹配问题。但是我在这个赛格故障问题中卡了两天。
我有 3 个文件:main.cpp、sgm.cpp、sgm.h。在main.cpp中,我为稍后将使用的两个3D矩阵创建空间。
unsigned short ***cost = new unsigned short**[leftImg.rows]; // cost matrix W*H*D
unsigned short ***aggreg = new unsigned short**[rightImg.rows]; // aggregated cost W*H*D
for(int row=0; row<leftImg.rows; row++) {
cost[row] = new unsigned short*[leftImg.cols];
aggreg[row] = new unsigned short*[rightImg.cols];
for(int col=0; col<leftImg.cols; col++) {
cost[row][col] = new unsigned short[disparityRange]();
// fill_n(cost[row][col], disparityRange, 0);
aggreg[row][col] = new unsigned short[disparityRange]();
}
}
然后在 sgm.cpp 中,我实现了一个函数:
void calculatePixelCost(unsigned short ***cost, cv::Mat& leftImg, cv::Mat& rightImg, int dRange) {
for(int i=0; i<leftImg.rows; i++)
for(int j=0; j<rightImg.cols; j++)
for(int d=0; d<dRange; d++) {
cost[i][j][d]=calculatePixelBT(leftImg, rightImg, i, j, d);
}
}
当我从main调用这个函数时.cpp通过编写:
sgm::calculatePixelCost(cost, leftImg, rightImg, disparityRange);
程序在调用它时就在这里崩溃了。波纹管是错误消息:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401ef9 in sgm::calculatePixelCost(unsigned short***, cv::Mat&, cv::Mat&, int) ()
在此处输入图像描述
我不知道哪里出了问题。指针cost
导致这种情况吗?
让我们分解一下。
首先,您正在构建的矩阵类型通常被称为"矩形矩阵",其中
- 所有行的长度相同
- 所有列的长度相同
- 所有楼层的长度相同
这意味着没有理由在此级别使用指针间接寻址。
所以我们的第一个重构:
unsigned short *cost = new short[leftImg.rows * leftImg.cols * disparityRange]{};
unsigned short *aggreg = new short[rightImg.rows * rightImg.cols * disparityRange]{};
//All of this is now irrelevant and unnecessary.
//for(int row=0; row<leftImg.rows; row++) {
//cost[row] = new unsigned short*[leftImg.cols];
//aggreg[row] = new unsigned short*[rightImg.cols];
//for(int col=0; col<leftImg.cols; col++) {
//cost[row][col] = new unsigned short[disparityRange]();
// fill_n(cost[row][col], disparityRange, 0);
//aggreg[row][col] = new unsigned short[disparityRange]();
//}
//}
您需要一个函数来帮助您访问正确的索引:
size_t get_index(size_t i, size_t j, size_t k, size_t rows, size_t cols, size_t floors) {
return i * cols * floors + j * floors + k;
}
所以在calculatePixelCost
中,改为编写这样的代码:
void calculatePixelCost(unsigned short *cost, cv::Mat& leftImg, cv::Mat& rightImg, int dRange) {
for(int i=0; i<leftImg.rows; i++)
for(int j=0; j<rightImg.cols; j++)
for(int d=0; d<dRange; d++) {
cost[get_index(i, j, d, leftImg.rows, leftImg.cols, dRange)] = calculatePixelBT(leftImg, rightImg, i, j, d);
}
}
此代码将帮助您缩小问题范围。但我们可以做得更好一点。
看,你不应该让你的指针像这样赤裸裸地暴露出来。孩子们可能正在查看您的代码!
因为我们身处C++地,处理这种情况的正确方法是在课堂上把事情总结起来。由于无论如何都需要一个合适的"3-dim 矩阵"对象,让我们创建一个合适的矩阵类。
class matrix {
size_t _rows, _columns, _floors;
//We'll use a std::vector object so that we no longer see any naked pointers.
std::vector<short> values;
public:
matrix(size_t rows, size_t columns, size_t floors) :
_rows(rows), _columns(columns), _floors(floors),
values(_rows * _columns * _floors)
{}
short & operator()(size_t row, size_t column, size_t floor) {
if(row >= _rows || column >= _columns || floor >= _floors)
throw std::runtime_error("Invalid access to matrix!");
return values[row * _columns * _floors + column * _floors + floor];
}
short const& operator()(size_t row, size_t column, size_t floor) const {
if(row >= _rows || column >= _columns || floor >= _floors)
throw std::runtime_error("Invalid access to matrix!");
return values[row * _columns * _floors + column * _floors + floor];
}
//We will not implement a resize function, as the logic of how it should work
//hasn't been established. It's probably better to simply allow new matrices
//to overwrite this one using the default-defined copy and move constructors.
//void resize(size_t rows, size_t columns, size_t floors);
bool operator==(matrix const& m) const {
if(!(_rows == m._rows && _columns == m._columns && _floors == m._floors)) return false;
return values == m.values;
}
size_t rows() const {return _rows;}
size_t columns() const {return _columns;}
size_t floors() const {return _floors;}
};
然后在代码中使用此矩阵:
matrix cost{leftImg.rows, leftImg.cols, disparityRange};
matrix aggreg{rightImg.rows, rightImg.cols, disparityRange};
以及这里:
void calculatePixelCost(matrix & cost, cv::Mat& leftImg, cv::Mat& rightImg, int dRange) {
for(int i=0; i<leftImg.rows; i++)
for(int j=0; j<rightImg.cols; j++)
for(int d=0; d<dRange; d++) {
cost(i, j, d) = calculatePixelBT(leftImg, rightImg, i, j, d);
}
}
看看这有多容易理解?是的,前期工作更多,但您将更容易推理代码正在做什么以及为什么需要这样做。
还有很多东西需要检查。例如,你对三嵌套 for 循环的依赖是可疑的,至少应该更好地重构。但是这些东西对于解决您的问题不太重要。
至少有了这个新代码,现在应该可以轻松识别出现问题的区域。