One Hot Encode function

asked 2020-08-18 09:42:15 -0500

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();                                           

  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;
edit retag flag offensive close merge delete


one-hot encoded matrix with n channels

seriously ? what do you need that for ? wouldn't it rather be n columns (and single channel) ?

and what exactly is in src ?

berak gravatar imageberak ( 2020-08-18 10:04:40 -0500 )edit

@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.

Der Luftmensch gravatar imageDer Luftmensch ( 2020-08-18 10:29:26 -0500 )edit

so this is basically a question of "C++ best practices"?

crackwitz gravatar imagecrackwitz ( 2020-08-22 17:06:32 -0500 )edit

No, this is how to make best use of the OpenCV API to get what I want with simplicity.

Der Luftmensch gravatar imageDer Luftmensch ( 2020-08-24 08:15:29 -0500 )edit