mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge pull request #24353 from alexlyulkov:al/fixed-cumsum-layer
Fixed CumSum dnn layer #24353 Fixes #20110 The algorithm had several errors, so I rewrote it. Also the layer didn't work with non constant axis tensor. Fixed it. Enabled CumSum layer tests from ONNX conformance.
This commit is contained in:
parent
4e60392040
commit
9bd14d5417
@ -47,73 +47,76 @@ public:
|
|||||||
inputs_arr.getMatVector(inputs);
|
inputs_arr.getMatVector(inputs);
|
||||||
outputs_arr.getMatVector(outputs);
|
outputs_arr.getMatVector(outputs);
|
||||||
|
|
||||||
// Get x tensor.
|
// Get input tensor.
|
||||||
const auto &src_mat = inputs[0];
|
const auto& src_mat = inputs[0];
|
||||||
const auto *src_ptr = src_mat.ptr<float>();
|
const auto* src_ptr = src_mat.ptr<float>();
|
||||||
|
|
||||||
// Get axis.
|
// Get target axis.
|
||||||
const int axis = normalize_axis(axis_raw, src_mat.dims);
|
int axis = inputs.size() > 1 ? parseAxis(inputs[1]) : axis_raw;
|
||||||
|
axis = normalize_axis(axis, src_mat.dims);
|
||||||
|
|
||||||
// Get y tensor.
|
|
||||||
auto &dst_mat = outputs[0];
|
// Get output tensor.
|
||||||
src_mat.copyTo(dst_mat);
|
auto& dst_mat = outputs[0];
|
||||||
auto *dst_ptr = dst_mat.ptr<float>();
|
auto* dst_ptr = dst_mat.ptr<float>();
|
||||||
|
|
||||||
// Get flags.
|
// Get flags.
|
||||||
const auto exclusive = exclusive_raw == 1;
|
const auto exclusive = exclusive_raw == 1;
|
||||||
const auto reverse = reverse_raw == 1;
|
const auto reverse = reverse_raw == 1;
|
||||||
|
|
||||||
// Get parameters to iterate outer dimension.
|
// Data with [dim_1, .. , dim_k-1, target_dim, dim_k+1, .. , dim_n]
|
||||||
|
// dimensions is represented here as [outer_dim, target_dim, inner_dim]
|
||||||
const size_t outer_size = src_mat.total(0, axis);
|
const size_t outer_size = src_mat.total(0, axis);
|
||||||
const size_t outer_step_length = src_mat.total(axis);
|
const size_t target_size = src_mat.size[axis];
|
||||||
|
const size_t inner_size = src_mat.total(axis + 1);
|
||||||
|
const size_t outer_step_length = target_size * inner_size;
|
||||||
|
|
||||||
// Get parameters to iterate inner dimension.
|
// Calculating steps in target dimensions
|
||||||
const size_t inner_size = src_mat.size[axis];
|
const int target_start = reverse ? target_size - 1 : 0;
|
||||||
|
const int target_stop = reverse ? -1 : target_size;
|
||||||
|
const int target_delta = reverse ? -1 : 1;
|
||||||
|
const int target_step = target_delta * inner_size;
|
||||||
|
|
||||||
if (!inner_size)
|
// If exclusive, the j-th output element would be the sum of the first (j-1) elements.
|
||||||
return;
|
// Otherwise, it would be the sum of the first j elements.
|
||||||
|
const int exclusive_delta = exclusive ? target_step : 0;
|
||||||
|
|
||||||
const size_t inner_step_length = src_mat.total(axis + 1);
|
for (size_t outer_idx = 0; outer_idx < outer_size; outer_idx++)
|
||||||
const int inner_step = (reverse ? -1 : 1) * inner_step_length;
|
|
||||||
const int inner_start = reverse ? inner_size - 1 : 0;
|
|
||||||
const int inner_stop = reverse ? -1 : inner_size;
|
|
||||||
const int inner_delta = reverse ? -1 : 1;
|
|
||||||
|
|
||||||
// Get parameters to populate channels.
|
|
||||||
const size_t num_channels = src_mat.total(axis + 1);
|
|
||||||
|
|
||||||
for (size_t outer_dim = 0; outer_dim < outer_size; outer_dim++)
|
|
||||||
{
|
{
|
||||||
const size_t outer_offset = outer_dim * outer_step_length;
|
const size_t target_offset = outer_idx * outer_step_length;
|
||||||
size_t src_offset = outer_offset + inner_start * inner_step_length;
|
|
||||||
|
|
||||||
// Populate first element of inner dimension.
|
// Handle first element of target dimension.
|
||||||
for (size_t channel = 0; channel < num_channels; channel++)
|
size_t first_inner_offset = target_offset + target_start * inner_size;
|
||||||
|
if (exclusive)
|
||||||
|
for (size_t inner_idx = 0; inner_idx < inner_size; inner_idx++)
|
||||||
|
dst_ptr[first_inner_offset + inner_idx] = 0.0f;
|
||||||
|
else
|
||||||
|
for (size_t inner_idx = 0; inner_idx < inner_size; inner_idx++)
|
||||||
|
dst_ptr[first_inner_offset + inner_idx] = src_ptr[first_inner_offset + inner_idx];
|
||||||
|
|
||||||
|
// Handle remaining elements of target dimension.
|
||||||
|
for (int target_idx = target_start + target_delta; target_idx != target_stop; target_idx += target_delta)
|
||||||
{
|
{
|
||||||
if (exclusive)
|
const size_t inner_offset = target_offset + target_idx * inner_size;
|
||||||
|
|
||||||
|
for (size_t inner_idx = 0; inner_idx < inner_size; inner_idx++)
|
||||||
{
|
{
|
||||||
dst_ptr[src_offset + channel] = 0.0f;
|
dst_ptr[inner_offset + inner_idx] = dst_ptr[inner_offset - target_step + inner_idx] +
|
||||||
}
|
src_ptr[inner_offset - exclusive_delta + inner_idx];
|
||||||
else
|
|
||||||
{
|
|
||||||
dst_ptr[src_offset + channel] = src_ptr[src_offset + channel];
|
|
||||||
src_offset += inner_step;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Populate remaining elements of inner dimension.
|
int parseAxis(const Mat& axis_mat) {
|
||||||
for (int inner_dim = inner_start + inner_delta; inner_dim != inner_stop; inner_dim += inner_delta)
|
CV_CheckEQ(axis_mat.total(), 1u, "Axis tensor should contain single value");
|
||||||
{
|
if (axis_mat.type() == CV_32SC1)
|
||||||
const size_t dst_offset = outer_offset + inner_dim * inner_step_length;
|
return axis_mat.at<int32_t>(0);
|
||||||
|
else
|
||||||
for (size_t channel = 0; channel < num_channels; channel++)
|
{
|
||||||
{
|
Mat axis_mat_int;
|
||||||
const size_t previous_dst_offset = dst_offset - inner_step;
|
axis_mat.convertTo(axis_mat_int, CV_32SC1);
|
||||||
dst_ptr[dst_offset + channel] = dst_ptr[previous_dst_offset + channel] +
|
return axis_mat_int.at<int32_t>(0);
|
||||||
src_ptr[src_offset + channel];
|
|
||||||
src_offset += inner_step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,13 @@
|
|||||||
"test_conv_with_strides_and_asymmetric_padding",
|
"test_conv_with_strides_and_asymmetric_padding",
|
||||||
"test_conv_with_strides_no_padding",
|
"test_conv_with_strides_no_padding",
|
||||||
"test_conv_with_strides_padding",
|
"test_conv_with_strides_padding",
|
||||||
|
"test_cumsum_1d",
|
||||||
|
"test_cumsum_1d_exclusive",
|
||||||
|
"test_cumsum_1d_reverse",
|
||||||
|
"test_cumsum_1d_reverse_exclusive",
|
||||||
|
"test_cumsum_2d_axis_0",
|
||||||
|
"test_cumsum_2d_axis_1",
|
||||||
|
"test_cumsum_2d_negative_axis",
|
||||||
"test_div_bcast",
|
"test_div_bcast",
|
||||||
"test_div_uint8",
|
"test_div_uint8",
|
||||||
"test_dropout_default_ratio",
|
"test_dropout_default_ratio",
|
||||||
|
@ -45,6 +45,13 @@
|
|||||||
"test_castlike_FLOAT_to_STRING_expanded",
|
"test_castlike_FLOAT_to_STRING_expanded",
|
||||||
"test_castlike_STRING_to_FLOAT_expanded",
|
"test_castlike_STRING_to_FLOAT_expanded",
|
||||||
"test_ceil",
|
"test_ceil",
|
||||||
|
"test_cumsum_1d",
|
||||||
|
"test_cumsum_1d_exclusive",
|
||||||
|
"test_cumsum_1d_reverse",
|
||||||
|
"test_cumsum_1d_reverse_exclusive",
|
||||||
|
"test_cumsum_2d_axis_0",
|
||||||
|
"test_cumsum_2d_axis_1",
|
||||||
|
"test_cumsum_2d_negative_axis",
|
||||||
"test_concat_1d_axis_negative_1",
|
"test_concat_1d_axis_negative_1",
|
||||||
"test_concat_3d_axis_1",
|
"test_concat_3d_axis_1",
|
||||||
"test_div",
|
"test_div",
|
||||||
|
@ -40,6 +40,13 @@
|
|||||||
"test_cast_STRING_to_FLOAT",
|
"test_cast_STRING_to_FLOAT",
|
||||||
"test_castlike_FLOAT_to_STRING_expanded",
|
"test_castlike_FLOAT_to_STRING_expanded",
|
||||||
"test_castlike_STRING_to_FLOAT_expanded",
|
"test_castlike_STRING_to_FLOAT_expanded",
|
||||||
|
"test_cumsum_1d",
|
||||||
|
"test_cumsum_1d_exclusive",
|
||||||
|
"test_cumsum_1d_reverse",
|
||||||
|
"test_cumsum_1d_reverse_exclusive",
|
||||||
|
"test_cumsum_2d_axis_0",
|
||||||
|
"test_cumsum_2d_axis_1",
|
||||||
|
"test_cumsum_2d_negative_axis",
|
||||||
"test_concat_1d_axis_negative_1",
|
"test_concat_1d_axis_negative_1",
|
||||||
"test_div_uint8",
|
"test_div_uint8",
|
||||||
"test_flatten_axis0",
|
"test_flatten_axis0",
|
||||||
|
@ -89,13 +89,6 @@
|
|||||||
"test_convtranspose_pad",
|
"test_convtranspose_pad",
|
||||||
"test_convtranspose_pads",
|
"test_convtranspose_pads",
|
||||||
"test_convtranspose_with_kernel",
|
"test_convtranspose_with_kernel",
|
||||||
"test_cumsum_1d",
|
|
||||||
"test_cumsum_1d_exclusive",
|
|
||||||
"test_cumsum_1d_reverse",
|
|
||||||
"test_cumsum_1d_reverse_exclusive",
|
|
||||||
"test_cumsum_2d_axis_0",
|
|
||||||
"test_cumsum_2d_axis_1",
|
|
||||||
"test_cumsum_2d_negative_axis",
|
|
||||||
"test_dequantizelinear",
|
"test_dequantizelinear",
|
||||||
"test_dequantizelinear_axis",
|
"test_dequantizelinear_axis",
|
||||||
"test_det_2d",
|
"test_det_2d",
|
||||||
|
Loading…
Reference in New Issue
Block a user