Search code examples
opencvazurekinect

Azure Kinect Recording Color Format


I'm attempting to read an Azure Kinect recording and save images from the frames. But, it is not possible to set the color_format, which causes problems when using imwrite.

I have read the recording documentation here: https://learn.microsoft.com/en-us/azure/Kinect-dk/azure-kinect-recorder.

By default, the format seems to be K4A_IMAGE_FORMAT_COLOR_MJPG. But I am unsure what parameter to pass in when creating the material. For BGRA32 it is CV_8UC4 and for depth images it is CV_16U.

I assume there are two ways to solve this problem, either by setting the color_format or figuring out what parameter is correct for the default format made by the recording.


Solution

  • You can access the rgb with OpenCV as if it were a normal webcam:

    VideoCapture cap(0); // open the default camera
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 3840);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 2160);
    if (!cap.isOpened())  // check if we succeeded
        return -1;
    Mat frame, img;
    for (;;)
    {
    
        cap >> frame; // get a new frame from camera
        cout << frame.cols << " x " << frame.rows << endl;
        resize(frame, img, Size(), 0.25, 0.25);
        imshow("frame", img);
        if (waitKey(30) >= 0) break;
    }
    

    No k4a function is called, no need to set the color format.

    If you want to use their SDK with jpeg format, they provide a function in one of their sample codes:

    long WriteToFile(const char *fileName, void *buffer, size_t bufferSize)
    {
        cout << bufferSize << endl;
        assert(buffer != NULL);
    
        std::ofstream hFile;
        hFile.open(fileName, std::ios::out | std::ios::trunc | std::ios::binary);
        if (hFile.is_open())
        {
            hFile.write((char *)buffer, static_cast<std::streamsize>(bufferSize));
            hFile.close();
        }
        std::cout << "[Streaming Service] Color frame is stored in " << fileName << std::endl;
    
        return 0;
    }
    

    You just call:

    image = k4a_capture_get_color_image(capture);
    WriteToFile("color.jpg", k4a_image_get_buffer(image), k4a_image_get_size(image));
    

    Finally, you can set the format to RGBA32:

    config.color_format = K4A_IMAGE_FORMAT_COLOR_BGRA32;
    

    and convert it into a OpenCV Mat:

    color_image = k4a_capture_get_color_image(capture);
        if (color_image)
        {
            uint8_t* buffer = k4a_image_get_buffer(color_image);        // get raw buffer
            cv::Mat colorMat(Hrgb, Wrgb, CV_8UC4, (void*)buffer, cv::Mat::AUTO_STEP);
            //do something with colorMat
            k4a_image_release(color_image);
        }
    

    More details on the last option here: How to convert k4a_image_t to opencv matrix? (Azure Kinect Sensor SDK)

    The data is slightly better with the last solution, but the buffer is significantly larger (33M vs ~1.5M) for 3840x2160.