One Hot Encode function
I have a matrix where each element is a class ID. I need to transform this matrix into a one-hot encoded matrix with n channels where n is the number of classes. I want to do this for any two data types (input and output) with a single compact function. How can I best make use of templates, CV_MAKETYPE
, etc?
My current function:
void one_hot_encode(cv::InputArray src, cv::OutputArray dst, int n_classes) {
dst.create(src.size(), CV_32FC(n_classes));
cv::Mat& dst_mat = dst.getMatRef();
dst_mat.setTo(0);
const cv::Mat src_mat = src.getMat();
for (int i = 0; i < src_mat.rows; ++i) {
auto* src_ptr = src_mat.ptr<uint8_t>(i);
auto* dst_ptr = dst_mat.ptr<float>(i);
for (int j = 0; j < src_mat.cols; ++j) {
dst_ptr[j*n_classes + src_ptr[j]] = 1;
}
}
}
seriously ? what do you need that for ? wouldn't it rather be n columns (and single channel) ?
and what exactly is in src ?
@berak, yes, this could be a 1D loop assuming continuous. The reason is to do this is for semantic segmentation. I have downstream processing that expects a softmaxed n-channel Mat and temporally smooths/aggregates results (with a perspective warp or dense optical flow, a poor man's LSTM). The network output in my current case is already argmaxed and because I don't have access to the softmax result, I'll do the next best thing and one-hot encode.
so this is basically a question of "C++ best practices"?
No, this is how to make best use of the OpenCV API to get what I want with simplicity.