Azure Kinect Recording Color Format - opencv

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.

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.

Related

Detect frame drop in OpenCV

How can I detect a dropped frame in OpenCV? Right now I am doing a check like the following:
int main() {
VideoCapture cap(-1);
if (!cap.isOpened()) {
cout << "Webcam is not open." << endl;
return -1;
}
Mat frame;
while (true) {
cap.read(frame);
if (!frame.empty()) {
imshow("frame", frame);
}
else {
cout << "No captured frame" << endl;
break;
}
}
}
But I still get messages saying "Camera frame dropped!" without my "No captured frame" message. What conditions result in the camera frame being dropped/how can I check for those conditions?
You can use this opencv function cap.get(CV_CAP_PROP_POS_MSEC) to obtain the presentation timestamp of a videoframe. This function returns an integer in multiples of time interval. If any frame drop, the timestamp would have skipped to (N+2)*time_interval instead of (N+1)*time_interval where N is your current frame number.

how to write a read DICOM file using VTK or ITK libraries?

I used vtkDICOMImageReader to read the DICOM file. I used the vtkImageThreshold to threshold a CT image. And now i want to write it back to my hard disk before further processing.
I tried vtkImageWriter library to write it back. But it is not working when i try to open the file using 3D slicer. I am much grateful if anyone can suggest me a methodology for writing Dicom files.
i have included my code here and i am trying to threshold a dicom image and viewing it. Then i would like to save the thresholded image as a dicom file. But i could not succeed in doing that. please help me.
thanks in advance.
#include <itkImageToVTKImageFilter.h>
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageThreshold.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageMapper3D.h>
#include <vtkImageActor.h>
#include <vtkImageCast.h>
#include <vtkNIFTIImageWriter.h>
#include <vtkImageMandelbrotSource.h>
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
int main(int argc, char* argv[])
{
std::string folder = argv[1];
vtkSmartPointer<vtkDICOMImageReader> reader =
vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetFileName(folder.c_str());
reader->Update();
vtkSmartPointer<vtkImageViewer2> imageViewer =
vtkSmartPointer<vtkImageViewer2>::New();
imageViewer->SetInputConnection(reader->GetOutputPort());
// threshold the images
vtkSmartPointer<vtkImageThreshold> imageThreshold =
vtkSmartPointer<vtkImageThreshold>::New();
imageThreshold->SetInputConnection(reader->GetOutputPort());
// unsigned char lower = 127;
unsigned char upper = 511;
imageThreshold->ThresholdByLower(upper);
imageThreshold->ReplaceInOn();
imageThreshold->SetInValue(0);
imageThreshold->ReplaceOutOn();
imageThreshold->SetOutValue(511);
imageThreshold->Update();
// Create actors
vtkSmartPointer<vtkImageActor> inputActor =
vtkSmartPointer<vtkImageActor>::New();
inputActor->GetMapper()->SetInputConnection(
reader->GetOutputPort());
vtkSmartPointer<vtkImageActor> thresholdedActor =
vtkSmartPointer<vtkImageActor>::New();
thresholdedActor->GetMapper()->SetInputConnection(
imageThreshold->GetOutputPort());
// There will be one render window
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(600, 300);
// And one interactor
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
// Define viewport ranges
// (xmin, ymin, xmax, ymax)
double leftViewport[4] = {0.0, 0.0, 0.5, 1.0};
double rightViewport[4] = {0.5, 0.0, 1.0, 1.0};
// Setup both renderers
vtkSmartPointer<vtkRenderer> leftRenderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(leftRenderer);
leftRenderer->SetViewport(leftViewport);
leftRenderer->SetBackground(.6, .5, .4);
vtkSmartPointer<vtkRenderer> rightRenderer =
vtkSmartPointer<vtkRenderer>::New();
renderWindow->AddRenderer(rightRenderer);
rightRenderer->SetViewport(rightViewport);
rightRenderer->SetBackground(.4, .5, .6);
leftRenderer->AddActor(inputActor);
rightRenderer->AddActor(thresholdedActor);
leftRenderer->ResetCamera();
rightRenderer->ResetCamera();
renderWindow->Render();
interactor->Start();
vtkSmartPointer<vtkNIFTIImageWriter> writer =
vtkSmartPointer<vtkNIFTIImageWriter>::New();
writer->SetInputConnection(reader->GetOutputPort());
writer->SetFileName("output");
writer->Write();
// writing the thresholded image to the hard drive.
//this is the part i am not able to code. Please can somebody help me please?
return EXIT_SUCCESS;
}
First, do you want to save out the thresholded image or just the image as read in? If not replace reader with imageThreshold
writer->SetInputConnection(reader->GetOutputPort())
From looking at the VTK tests of NIFTI readers and writers the following options may be required...
writer->SetNIFTIHeader(reader->GetNIFTIHeader())
writer->SetQFac(reader->GetQFac());
writer->SetTimeDimension(reader->GetTimeDimension());
writer->SetTimeSpacing(reader->GetTimeSpacing());
writer->SetRescaleSlope(reader->GetRescaleSlope());
writer->SetRescaleIntercept(reader->GetRescaleIntercept());
writer->SetQFormMatrix(reader->GetQFormMatrix());
I would test with adding these options and then see what you get
I think VTK is a little bit confused to process image. I only use it to display image.I wrote a piece of code for you. The code which read , threshold and write dicom image is below.It use only itk. I think it fills the bill.
#include "itkBinaryThresholdImageFilter.h"
#include "itkImageFileReader.h"
#include "itkGDCMImageIO.h"
#include "itkImageFileWriter.h"
#include "itkImage.h"
int main () {
typedef unsigned char InputPixelType ; //Pixel Type of Input image
typedef unsigned char OutputPixelType; //Pixel Type of Output image
const unsigned int InputDimension = 2; //Dimension of image
typedef itk::Image < InputPixelType, InputDimension > InputImageType; //Type definition of Input Image
typedef itk::Image < InputPixelType, InputDimension > OutputImageType;//Type definition of Output Image
typedef itk::ImageSeriesReader< InputImageType > ReaderType;//Type definition of Reader
typedef itk::BinaryThresholdImageFilter<InputImageType, OutputImageType > FilterType; // Type definition of Filter
typedef itk::ImageFileWriter<OutputImageType> ImageWriterType; //Definition of Writer of Ouput image
typedef itk::GDCMImageIO ImageIOType; //Type definition of Image IO for Dicom images
//Starts Reading Process
ReaderType::Pointer reader = ReaderType::New(); //Creates reader
ImageIOType::Pointer gdcmImageIO_input = ImageIOType::New(); //Creates ImageIO object for input image
reader->SetImageIO( gdcmImageIO_input ); // Sets image IO of reader
reader->SetFileNames( "example_image.dcm" ); // Sets filename to reader
//Exceptional handling
try
{
reader->UpdateLargestPossibleRegion();
}
catch (itk::ExceptionObject & e)
{
std::cerr << "exception in file reader " << std::endl;
std::cerr << e << std::endl;
return EXIT_FAILURE;
}
// Start filtering process
FilterType::Pointer filter = FilterType::New(); //Creates filter
filter->SetInput( reader->GetOutput() );
filter->SetOutsideValue( 0); // Set pixel value which are out of lower and upper threshold value
filter->SetInsideValue( 255 );// Set pixel value which are within lower and upper threshold value
filter->SetLowerThreshold( 25 ); // Lower threshold value 25
filter->SetUpperThreshold( 150 );// Upper threshold value 150
filter->Update();
//Starts Writing Process
ImageWriterType::Pointer imageWriter = ImageWriterType::New(); // Creates writer
ImageIOType::Pointer gdcmImageIO_output = ImageIOType::New(); // Creates Image IO object for output image
imageWriter->SetImageIO( gdcmImageIO_output ); // Set image IO as dicom
imageWriter->SetInput(filter->GetOutput() ); // Connects output of filter with to input of writer
imageWriter->SetFileName(example_image_thresholded.dcm); // Sets output file name
//Exceptional handling
try
{
imageWriter->Update();
}
catch ( itk::ExceptionObject &exception )
{
std::cerr << "Exception in file writer ! " << std::endl;
std::cerr << exception << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

Error while capturing video for a pre-defined time period

This program captures video until I press Esc. But I need to modify this program and capture video for 30s.
After recording the video it plays very fast and the video length reduces. I tried to add waitKey at the end, but it still doesn't work. After recording the video length should be the same. How can I do that? Any suggestions?
int main( int argc, const char** argv )
{
using namespace std;
using namespace cv;
VideoCapture cap(0);
while(!(cap.isOpened() && cap.grab()))
{
cout << "Camera not ready" << endl;
}
VideoWriter Writer("D:/MyVideo.avi", CV_FOURCC('P','I','M','1'),20,Size(640,480), true);
while (waitKey(30)!= 27)
{
Mat frame;
cap >> frame;
Writer.write(frame);
imshow("D:/MyVideo", frame);
}
}
int64 t0 = cv::getTickCount();
while (waitKey(30)!= 27)
{
Mat frame;
cap >> frame; // read a new frame from video
Writer.write(frame); //writer the frame into the file
double t = (cv::getTickCount() - t0) / cv::getTickFrequency();
if (t > 30)
break;
...
// now, we need to adjust to the desired framerate of 20fps,
// so we need to sleep for 1000/20 = 50 milliseconds
// either have a window, and use waitKey():
// imshow("lalala", frame);
// waitKey(50);
// or just sleep(), unfortunately system dependant ;(
// win:
// Sleep(50);
// linux, etc.:
// usleep(50);
}

using cvRetrieveFrame get strange image

I am reading a avi file, and do some background subtrcation work. The wierd thing is when I use cvRetrieveFrame, I got a strange image, like below:
origin:
cvRetrieveFrame returns:
I don't know what's the problem. Here is my code snippet.
CvCapture* readerAvi = cvCaptureFromAVI( filename.c_str() );
if(readerAvi == NULL)
{
std::cerr << "Could not open AVI file." << std::endl;
return 0;
}
// retrieve information about AVI file
cvQueryFrame(readerAvi); //....get some information, width, height, ....
// grad next frame from input video stream
if(!cvGrabFrame(readerAvi))
{
std::cerr << "Could not grab AVI frame." << std::endl;
return 0;
}
frame_data = cvRetrieveFrame(readerAvi);

After reading multiple frames from a camera, OpenCV suddenly always fails to read frames. How do I diagnose this?

I run a program similar to the one in this question: https://stackoverflow.com/a/8719192/26070
#include <opencv/highgui.h>
#include <iostream>
/** #function main */
int main( int argc, char** argv )
{
cv::VideoCapture vcap;
cv::Mat image;
const std::string videoStreamAddress = "rtsp://192.0.0.1:8081/live.sdp";
//open the video stream and make sure it's opened
if(!vcap.open(videoStreamAddress)) {
std::cout << "Error opening video stream or file" << std::endl;
return -1;
}
for(;;) {
if(!vcap.read(image)) {
std::cout << "No frame" << std::endl;
cv::waitKey(500);
} else {
cv::imshow("Output Window", image);
}
if(cv::waitKey(1) >= 0) break;
}
}
The program runs fine for a certain amount of time (about one minute or so) and then the call to read() (method from cv::VideoCapture) always returns false.
The output is as follows:
[mpeg4 # 00da27a0] ac-tex damaged at 22 7
[mpeg4 # 00da27a0] Error at MB: 309
No frame
No frame
No frame
Note: the first two lines are not always present.
So, how can I determine what the root of the problem is?

Resources