У меня есть код, который создает пару пирамид изображений, хранящихся как std::vector<cv::Mat_<T>>
. Одна из пирамид представляет собой двоичную маску, хранящуюся в массиве без знака. Эта пирамида, кажется, создает хорошо. Другая пирамида - это пирамида данных с плавающей точкой. Он создается с использованием только данных на предыдущих уровнях, где маска истинна.
Моя проблема возникает, когда я размещаю данные для этих пирамид. Я выделяю пустое поле данных и затем перемещаю его в вектор (хотя я могу использовать cv::Mat::zeros
). Сегфоут происходит при первоначальном размещении. Еще более странно, что это не происходит на первой итерации. В чем причина segfault ???
Пример кода:
template <typename T>
auto CreateMaskedPyramid(const cv::Mat_<unsigned char>& input_mask,
const cv::Mat_<T>& input_data, int minimum_size) {
assert(input_mask.cols == input_data.cols);
assert(input_mask.rows == input_data.rows);
std::vector<cv::Mat_<unsigned char>> masks(1);
input_mask.copyTo(masks.back());
std::vector<cv::Mat_<T>> datas(1);
input_data.copyTo(datas.back());
cv::Size size = input_data.size();
while (std::min(masks.back().rows, masks.back().cols) / 2 > minimum_size) {
size = size / 2;
masks.emplace_back();
datas.emplace_back();
masks.back() = cv::Mat_<unsigned char>(size, static_cast<unsigned char>(0));
cv::Mat_<T> temp(size, static_cast<T>(0));
datas.back() = std::move(temp);
const auto& previous_mask = masks.at(masks.size() - 2);
const auto& previous_data = datas.at(masks.size() - 2);
for (int y = 0; y < masks.back().rows; y++) {
for (int x = 0; x < masks.back().cols; x++) {
unsigned char num_valid = 0;
if (previous_mask.at<float>(y * 2, x * 2) > 0) {
num_valid += 1;
datas.back().template at<T>(y, x) += previous_data.template at<T>(y * 2, x * 2);
}
if (previous_mask.at<float>(y * 2, x * 2 + 1) > 0) {
num_valid += 1;
datas.back().template at<T>(y, x) += previous_data.template at<T>(y * 2, x * 2 + 1);
}
if (previous_mask.at<float>(y * 2 + 1, x * 2) > 0) {
num_valid += 1;
datas.back().template at<T>(y, x) += previous_data.template at<T>(y * 2 + 1, x * 2);
}
if (previous_mask.at<float>(y * 2 + 1, x * 2 + 1) > 0) {
num_valid += 1;
datas.back().template at<T>(y, x) += previous_data.template at<T>(y * 2 + 1, x * 2 + 1);
}
if (num_valid != 0) {
datas.back().template at<T>(y, x) /= static_cast<float>(num_valid);
} else {
datas.back().template at<T>(y, x) = 0.0f;
}
masks.back().template at<T>(y, x) = num_valid > 0 ? 255 : 0;
}
}
}
return std::make_tuple(std::move(masks), std::move(datas));
}
int main(int argc, char** argv) {
assert(argc > 1);
auto fname = std::string(argv[1]);
cv::Mat image = cv::imread(fname, cv::IMREAD_GRAYSCALE);
cv::Mat_<unsigned char> mask;
cv::threshold(image, mask, 127, 255, cv::THRESH_BINARY);
cv::Mat_<float> data;
image.convertTo(data, data.type());
auto [mask_pyramid, data_pyramid] = CreateMaskedPyramid<float>(image, data, 64);
return mask_pyramid.size() == data_pyramid.size() ? 0 : 255;
}
При использовании GDB трассировка стека переходит к cv :: Mat :: create, вызываемому из cv::Mat_<T> temp(size, static_cast<T>(0));