Hello everyone, I am trying to apply cropping using NvBufSurfTransform on my Jetson Orin NX device with JetPack 6.2.
At the very beginning, when creating the destination surface, I am using src_rect
parameters because if I try to use the values from takePhotoCropW
and takePhotoCropH
, I get a grey image at crop time and the cropped image does not appear. (I need help with this part.)
Then I configure the transform parameters, perform the transformation, and process the image using processV4L2Fd.
Here’s where my question and issue arise:
If I use the code like below, cropping is performed successfully, but the resulting photo has incorrect width and height values (it comes out as if it’s not cropped, with the original width and height):
Code:
else if(takePhotoCropEnable)
{
NvBufSurfaceCreateParams params = {};
params.width = src_rect.width;
params.height = src_rect.height;
params.memType = NVBUF_MEM_SURFACE_ARRAY;
params.layout = NVBUF_LAYOUT_PITCH;
params.colorFormat = NVBUF_COLOR_FORMAT_YUV420;
// Create buffer
int ret = NvBufSurfaceCreate(&dstSurface, 1, ¶ms);
if (ret != 0 || !dstSurface) {
std::cerr << "Failed to create destination surface: Error " << ret << std::endl;
return -1;
}
// Yerel bir src_rect nesnesi oluşturuyoruz
NvBufSurfTransformRect src_rect_instance = {};
src_rect_instance.width = takePhotoCropW;
src_rect_instance.height = takePhotoCropH;
src_rect_instance.left = takePhotoCropX;
src_rect_instance.top = takePhotoCropY;
// Configure transform parameters
transform_params.src_rect = &src_rect_instance;
// transform_params.src_rect.width = takePhotoCropW;
// transform_params.src_rect.height = takePhotoCropH;
// transform_params.src_rect.left = takePhotoCropX;
// transform_params.src_rect.top = takePhotoCropY;
transform_params.transform_flag = NVBUFSURF_TRANSFORM_CROP_SRC;
transform_params.transform_flip = NvBufSurfTransform_None;
transform_params.transform_filter = NvBufSurfTransformInter_Algo3;
// Perform transformation
if (NvBufSurfaceFromFd(src->frameInfo->fd, (void**)&srcSurface) != 0) {
std::cerr << "NvBufSurfaceFromFd failed!" << std::endl;
}
NvBufSurfTransform_Error transform_error = NvBufSurfTransform(srcSurface, dstSurface, &transform_params);
if (transform_error != NvBufSurfTransformError_Success) {
std::cerr << "NvBufSurfTransform failed: " << transform_error << std::endl;
NvBufSurfaceDestroy(dstSurface);
return -1;
}
// Process the buffer
if (!processV4L2Fd(dstSurface->surfaceList[0].bufferDesc, selectedJpegQuality, takePhotoCropW, takePhotoCropH, imageWritePath)) {
std::cerr << "Failed to process buffer" << std::endl;
}
// Cleanup
NvBufSurfaceDestroy(dstSurface);
}
else
{
processV4L2Fd(src->frameInfo->fd, selectedJpegQuality, src->width, src->height, imageWritePath);
}
Original Photo:
Cropped Photo (wrong width height):
If I use the code below, the cropping works, and the width/height are correct, but the remaining area shows up as green.
else if(takePhotoCropEnable)
{
NvBufSurfaceCreateParams params = {};
params.width = src_rect.width;
params.height = src_rect.height;
params.memType = NVBUF_MEM_SURFACE_ARRAY;
params.layout = NVBUF_LAYOUT_PITCH;
params.colorFormat = NVBUF_COLOR_FORMAT_YUV420;
// Create buffer
int ret = NvBufSurfaceCreate(&dstSurface, 1, ¶ms);
if (ret != 0 || !dstSurface) {
std::cerr << "Failed to create destination surface: Error " << ret << std::endl;
return -1;
}
NvBufSurfTransformRect src_rect_instance = {};
src_rect_instance.width = takePhotoCropW;
src_rect_instance.height = takePhotoCropH;
src_rect_instance.left = takePhotoCropX;
src_rect_instance.top = takePhotoCropY;
NvBufSurfTransformRect dst_rect_instance = {};
dst_rect_instance.width = takePhotoCropW;
dst_rect_instance.height = takePhotoCropH;
dst_rect_instance.left = 0;
dst_rect_instance.top = 0;
transform_params.src_rect = &src_rect_instance;
transform_params.dst_rect = &dst_rect_instance;
transform_params.transform_flag = NVBUFSURF_TRANSFORM_CROP_SRC | NVBUFSURF_TRANSFORM_CROP_DST;
transform_params.transform_flip = NvBufSurfTransform_None;
transform_params.transform_filter = NvBufSurfTransformInter_Algo3;
if (NvBufSurfaceFromFd(src->frameInfo->fd, (void**)&srcSurface) != 0) {
std::cerr << "NvBufSurfaceFromFd failed!" << std::endl;
}
NvBufSurfTransform_Error transform_error = NvBufSurfTransform(srcSurface, dstSurface, &transform_params);
if (transform_error != NvBufSurfTransformError_Success) {
std::cerr << "NvBufSurfTransform failed: " << transform_error << std::endl;
NvBufSurfaceDestroy(dstSurface);
return -1;
}
if (!processV4L2Fd(dstSurface->surfaceList[0].bufferDesc, selectedJpegQuality, dstSurface->surfaceList[0].width, dstSurface->surfaceList[0].height, imageWritePath)) {
std::cerr << "Failed to process buffer" << std::endl;
}
NvBufSurfaceDestroy(dstSurface);
}
else
{
processV4L2Fd(src->frameInfo->fd, selectedJpegQuality, src->width, src->height, imageWritePath);
}
Cropped Photo:
Here is the content of the processV4L2Fd
function:
bool ArgusAPI::processV4L2Fd(int32_t fd, std::string &filePath)
{
std::ofstream *outputFile = new std::ofstream(filePath.c_str());
if (outputFile)
{
unsigned long size = m_OutputBufferSize;
#ifdef JETPACK_6_2
unsigned char *buffer = m_OutputBuffer.get();
m_JpegEncoder->encodeFromFd(fd, JCS_YCbCr, &buffer, size,
m_configuration->takePhoto.jpegQuality);
outputFile->write((char *)buffer, size);
#endif
#if defined(JETPACK_4_6) || defined(JETPACK_4_4_1)
unsigned char *buffer = m_OutputBuffer;
m_JpegEncoder->encodeFromFd(fd, JCS_YCbCr, &buffer, size,
m_configuration->takePhoto.jpegQuality);
outputFile->write((char *)buffer, size);
#endif
delete outputFile;
APP_LOG(Ekin::Logger::LogLevel::INFO_LOG, "Jpg writed as :" + filePath);
}
return true;
}
My goal here is to perform a successful crop using the width, height, x, and y values.
Thank you in advance for your response.