Kithara使用OpenCV + QT 进行特征检测
目录
- Kithara使用OpenCV + QT 进行特征检测
- OpenCV 特征检测简介
- Qt应用框架简介
- 项目说明
- 关键代码
- 抖动测试
- 测试平台:
- 测试结果:
- 结论
OpenCV 特征检测简介
OpenCV是一个开源的计算机视觉库,提供了各种图像处理和计算机视觉算法的实现。特征检测是其中重要的功能之一。
特征检测是一种在图像中寻找关键点或感兴趣区域的技术。这些关键点通常具有以下特征:边缘、角点、斑点等。特征检测算法可以帮助我们定位和识别图像中的物体以及进行图像配准、目标跟踪等应用。
OpenCV提供了多种特征检测算法的实现,包括SIFT、SURF、ORB等。其中,SIFT(尺度不变特征变换)和SURF(速度ed特征变换)是两种常用的基于局部特征的算法,它们具有尺度不变性和旋转不变性,适用于广泛的图像变换和缩放操作。ORB(Oriented FAST and Rotated BRIEF)是一种结合了FAST关键点检测器和BRIEF描述符的快速算法,适用于实时应用。
特征检测的步骤通常包括关键点检测、关键点描述和匹配。关键点检测是在图像中找到具有显著性质的点,如边缘、角点等。关键点描述是为每个关键点生成一个描述符,用于表示其局部特征。匹配是将两个图像中的关键点进行配对,找到相对应的点对。
特征检测在计算机视觉领域有广泛的应用,如图像配准、目标识别、物体检测、增强现实等。通过使用OpenCV提供的特征检测算法,可以方便地实现这些应用。
关于Kithara如何调用OpenCV,以及如何编译适用于Kithara的OpenCV开发库可以查看 Kithara与OpenCV (一)
Qt应用框架简介
Qt是一个跨平台的C++应用程序开发框架。它提供了一套丰富的库和工具,用于开发图形用户界面(GUI)应用程序、网络应用程序和嵌入式应用程序,由于本章文章重点并不是Qt,所以就不展开说明,如果对Qt感兴趣,可以去Qt官网或者其他博客。
项目说明
使用Kithara Windows实时套件和OpenCV的组合,可以进行圆形检测,并结合Qt图形化应用框架实时显示检测图像,可以选择不同网口的摄像头和调节检测圆的参数,并测试处理抖动。
编写流程:
- 导入Kithara Windows实时套件和OpenCV库。
- 使用Qt图形化应用框架创建一个界面,包括一个图像显示区域和参数调节区域。
- 初始化Kithara并打开摄像头,开始实时获取图像。
- 在任务处理中,将实时获取的图像传递给OpenCV进行圆形检测。
- 根据检测结果,在图像上绘制圆形,并通过共享内存j将数据回传到应用层将图像实时显示在界面的图像显示区域中。
- 在参数调节区域中,添加可调节的参数,如圆形半径、最小阈值等,通过滑动条或输入框来修改参数。
- 当参数发生变化时,重新进行圆形检测,并在图像上实时显示检测结果。
- 可以添加其他功能,进行扩展。
- 结束时,释放资源和关闭摄像头。
关键代码
// 这是实时任务将运行的函数,并对接收到的图像执行 OpenCV 操作。只有实时任务才应调用 OpenCV 函数。
KSError __stdcall OpenCVcallback(void * /*pArgs*/, void * /*pContext*/)
{
// 在内核层模式下自动并行化 OpenCV 可能会与您的实时应用程序冲突。 建议关闭自动并行化,除非真的需要
// 禁用并行化
cv::setNumThreads(0);
// 表示已准备好处理图像。
krenel_data_ptr_->ready = 1;
// 图形抖动性测试
int64 last_diff_time {0};
int is_valid_time = 0; // 时间是否有效 0 无效 1 时间有效 2 时间差有效
int count = 0; // 计数器
int64 jitter_time_sum {0}; // 抖动总时间
// 处理循环,此循环仅在发出中止信号时停止。
for (;;)
{
// 等待图像接收或停止的通知。
KSError error = KS_waitForEvent(krenel_data_ptr_->image_received_event_handle, KSF_NO_FLAGS, 0);
if (error != KS_OK) { KS_printK("KS_waitForEvent failed! \n"); }
if (krenel_data_ptr_->abort != 0) { break; }
// 计数器
count++;
// 获取当前时间,用于计算图像处理的抖动时间
int64 last_time {0};
error = KS_getClock(&last_time, KS_CLOCK_MEASURE_HIGHEST);
if (error != KS_OK) { return error; }
// 获取接收到的图像数据的缓冲区
KSCameraBlock *camera_block;
void *image_data;
error = KS_recvCameraImage(krenel_data_ptr_->stream_handle, &image_data, &camera_block,KSF_NO_FLAGS);
if (error != KS_OK)
{
krenel_data_ptr_->ready = 1;
continue;
}
//如果接收到的块类型不是图像,我们跳过。在任何情况下,如果 KS_recvCameraImage() 成功接收到的缓冲区必须使用 KS_releaseCameraImage() 释放。
if (camera_block->blockType != KS_CAMERA_BLOCKTYPE_IMAGE)
{
KS_releaseCameraImage(krenel_data_ptr_->stream_handle, image_data, KSF_NO_FLAGS);
break;
}
// 在构建 OpenCV cv::Mat 之前,请检查接收到的图像是否具有正确的像素格式。
const auto *image_block = reinterpret_cast<KSCameraImage *>(camera_block);
// 图像转换
cv::Mat image = CreateMat(image_block->height, image_block->width, image_block->pixelFormat, image_data, image_block->linePadding);
// 圆形检测
image = CircleDetect(krenel_data_ptr_->check_circle_param, image);
error = KS_releaseCameraImage(krenel_data_ptr_->stream_handle, image_data, KSF_NO_FLAGS);
if (error != KS_OK) { KS_printK("KS_releaseCameraImage failed! \n"); }
// 填充图像信息到共享内存中
krenel_data_ptr_->image_info.image_height = image.rows;
krenel_data_ptr_->image_info.image_width = image.cols;
krenel_data_ptr_->image_info.pixel_format = image_block->pixelFormat;
if (image_block->pixelFormat == KS_CAMERA_PIXEL_MONO_8)
{
KS_memCpy(pixel_buffer_, image.data, (int) image.cols * image.rows, KSF_NO_FLAGS);
}
else if (image_block->pixelFormat == KS_CAMERA_PIXEL_BGR_8)
{
KS_memCpy(pixel_buffer_, image.data, (int) image.cols * image.rows * 3, KSF_NO_FLAGS);
}
// 图形处理完成后,减去上次处理完成的时间
int64 time {0};
error = KS_getClock(&time, KS_CLOCK_MEASURE_HIGHEST);
if (error != KS_OK) { return error; }
// 检测圆处理时间
const int64 diff_time = time - last_time;
int64 time_cyc = diff_time;
KS_convertClock(&time_cyc, KS_CLOCK_MEASURE_HIGHEST, KS_CLOCK_MACHINE_TIME, KSF_NO_FLAGS);
krenel_data_ptr_->jitter_value.time_cyc = time_cyc;
if (is_valid_time == 0)
{
last_diff_time = diff_time;
is_valid_time = 1;
}
else
{
// 处理时间的抖动
const int64 jitter_time = diff_time - last_diff_time;
int64 single_time = jitter_time;
KS_convertClock(&single_time, KS_CLOCK_MEASURE_HIGHEST, KS_CLOCK_MACHINE_TIME, KSF_NO_FLAGS); // 100 ns 为单位
last_diff_time = diff_time;
jitter_time_sum += single_time;
if (krenel_data_ptr_->jitter_value.lat_min > single_time)
{
krenel_data_ptr_->jitter_value.lat_min = single_time;
}
if (krenel_data_ptr_->jitter_value.lat_max < single_time)
{
krenel_data_ptr_->jitter_value.lat_max = single_time;
}
krenel_data_ptr_->jitter_value.lat_avg = jitter_time_sum / count;
krenel_data_ptr_->jitter_value.cur_val = single_time;
}
krenel_data_ptr_->ready = 1;
}
return KS_OK;
}
抖动测试
测试平台:
测试结果:
结论
Kithara Windows实时套件得益于独占CPU处理OpenCV对图像中圆的检测,无论Windows负载如何,检测任务任能稳定处理。
我也同时测试了不同平台对检测任务的影响,如图:
可以同样的检测任务,抖动出现较大差异,说明性能检测的CPU对图像处理有一定的影响,测试过程中还发现,不同算法,图像的复杂度等均有一定影响。