1、G-API是什么?能干什么?
G-API 是OpenCV针对图像处理算法流程开发的目标是以构建图为方法,增加不同后端进行计算优化,以使图像处理任务更加轻量级和快速的新框架。比如整体考虑GPU上的算法流程、系统减少优化显存访问,可有效提高计算速度。
2、笔者使用的是opencv v4.5.5版本源码,
https://github.com/opencv/opencv/tree/4.5.5/modules/gapi
自己写了一个demo来测试canny和findContours算子的性能,电脑CPU 4核,8线程,内存8GB:
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
void normal()
{
cv::Mat srcImage = cv::imread("D:\\allike\\Image_20210707220756198.jpg");
cv::Mat dstImage;
std::vector<std::vector<cv::Point>> vvtPointContours; //类型不能是cv::Point2f,否则会出错,提示matrix_wrap.cpp:1385: error
double t1 = (double)cv::getTickCount();
cv::cvtColor(srcImage, dstImage, cv::COLOR_BGR2GRAY);
cv::blur(dstImage, dstImage, cv::Size(5, 5));
cv::Canny(dstImage, dstImage, 20, 100, 3);
double t2 = ((double)cv::getTickCount() - t1) / cv::getTickFrequency() * 1000;
std::cout << "Run Time 1,Canny: " << t2 << " ms\n";
t2 = (double)cv::getTickCount();
cv::findContours(dstImage, vvtPointContours, cv::RETR_LIST, cv::CHAIN_APPROX_NONE, cv::Point(0, 0));
double t3 = ((double)cv::getTickCount() - t2) / cv::getTickFrequency() * 1000;
std::cout << "Run Time 1,findContours: " << t3 << " ms\n";
}
void gapi()
{
cv::Mat srcImage = cv::imread("D:\\allike\\Image_20210707220756198.jpg");
cv::Mat dstImage;
//G-API只追踪管线的操作以及如何连接的。G-API的数据对象(cv::GMat)是用以连接各种操作的。
//cv::GMat in则是一个为空的GMat信号,用于告知计算的开始。
//然后实例化cv::GComputation这个对象。此对象把输入/输出(input/output)数据当做参数(在本例中依次是in和out这两个cv::GMat对象),
//并基于in和out的中的数据流来重建调用图。
double t1 = (double)cv::getTickCount();
//https://github.com/opencv/opencv/tree/4.5.5/modules/gapi/samples
cv::GMat in;
cv::GMat gray = cv::gapi::BGR2Gray(in);
cv::GMat imgBlur = cv::gapi::blur(gray, cv::Size(5, 5));
cv::GMat out = cv::gapi::Canny(imgBlur, 20, 100, 3);
cv::GComputation ac(in, out);
ac.apply(srcImage, dstImage);
double t2 = ((double)cv::getTickCount() - t1) / cv::getTickFrequency() * 1000;
std::cout << "Run Time 2,Canny: " << t2 << " ms\n";
t2 = (double)cv::getTickCount();
//https://github.com/opencv/opencv/tree/4.5.5/modules/gapi/test/common
//https://github.com/opencv/opencv/tree/4.5.5/modules/gapi/test/common/gapi_imgproc_tests_common.hpp
std::vector<std::vector<cv::Point>> out_cnts_gapi;
cv::Point offset = cv::Point();
cv::GMat g_in;
cv::GOpaque<cv::Point> gOffset;
cv::GArray<cv::GArray<cv::Point>> outCts = cv::gapi::findContours(g_in, cv::RETR_LIST, cv::CHAIN_APPROX_NONE, gOffset);
cv::GComputation c(GIn(g_in, gOffset), GOut(outCts));
c.apply(gin(dstImage, offset), gout(out_cnts_gapi));
double t3 = ((double)cv::getTickCount() - t2) / cv::getTickFrequency() * 1000;
std::cout << "Run Time 2,findContours: " << t3 << " ms\n";
cv::namedWindow("gapi", cv::WINDOW_NORMAL);
//cv::imshow("gapi", dstImage);
//cv::waitKey(0);
}
int main(int argc, char *argv[])
{
normal();
gapi();
return 0;
}
测试结果:
Run Time 1,Canny: 120.699 ms
Run Time 1,findContours: 52.0882 ms
Run Time 2,Canny: 94.1655 ms
Run Time 2,findContours: 45.5371 ms
加速效果还是有一些的!
3、官方测试用例
https://github.com/opencv/opencv/tree/4.5.5/modules/gapi/test/common
https://github.com/opencv/opencv/tree/4.5.5/modules/gapi/samples
4、参考文献