Merge pull request #13030 from dmatveev:tutorial
* G-API: First steps with tutorial * G-API Tutorial: First iteration * G-API port of anisotropic image segmentation tutorial; * Currently works via OpenCV only; * Some new kernels have been required. * G-API Tutorial: added chapters on execution code, inspection, and profiling * G-API Tutorial: make Fluid kernel headers public For some reason, these headers were not moved to the public headers subtree during the initial development. Somehow it even worked for the existing workloads. * G-API Tutorial: Fix a couple of issues found during the work * Introduced Phase & Sqrt kernels, OCV & Fluid versions * Extended GKernelPackage to allow kernel removal & policies on include() All the above stuff needs to be tested, tests will be added later * G-API Tutorial: added chapter on running Fluid backend * G-API Tutorial: fix a number of issues in the text * G-API Tutorial - some final updates - Fixed post-merge issues after Sobel kernel renaming; - Simplified G-API code a little bit; - Put a conclusion note in text. * G-API Tutorial - fix build issues in test/perf targets Public headers were refactored but tests suites were not updated in time * G-API Tutorial: Added tests & reference docs on new kernels * Phase * Sqrt * G-API Tutorial: added link to the tutorial from the main module doc * G-API Tutorial: Added tests on new GKernelPackage functionality * G-API Tutorial: Extended InRange tests to cover 32F * G-API Tutorial: Misc fixes * Avoid building examples when gapi module is not there * Added a volatile API disclaimer to G-API root documentation page * G-API Tutorial: Fix perf tests build issue This change came from master where Fluid kernels are still used incorrectly. * G-API Tutorial: Fixed channels support in Sqrt/Phase fluid kernels Extended tests to cover this case * G-API Tutorial: Fix text problems found on team review
This commit is contained in:
committed by
Alexander Alekhin
parent
1d10d56651
commit
85fad1504a
+13
-6
@@ -10,7 +10,9 @@
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
//! [calcGST_proto]
|
||||
void calcGST(const Mat& inputImg, Mat& imgCoherencyOut, Mat& imgOrientationOut, int w);
|
||||
//! [calcGST_proto]
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -26,6 +28,7 @@ int main()
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! [main_extra]
|
||||
//! [main]
|
||||
Mat imgCoherency, imgOrientation;
|
||||
calcGST(imgIn, imgCoherency, imgOrientation, W);
|
||||
@@ -45,32 +48,36 @@ int main()
|
||||
|
||||
normalize(imgCoherency, imgCoherency, 0, 255, NORM_MINMAX);
|
||||
normalize(imgOrientation, imgOrientation, 0, 255, NORM_MINMAX);
|
||||
|
||||
imwrite("result.jpg", 0.5*(imgIn + imgBin));
|
||||
imwrite("Coherency.jpg", imgCoherency);
|
||||
imwrite("Orientation.jpg", imgOrientation);
|
||||
//! [main_extra]
|
||||
return 0;
|
||||
}
|
||||
//! [calcGST]
|
||||
//! [calcJ_header]
|
||||
void calcGST(const Mat& inputImg, Mat& imgCoherencyOut, Mat& imgOrientationOut, int w)
|
||||
{
|
||||
Mat img;
|
||||
inputImg.convertTo(img, CV_64F);
|
||||
inputImg.convertTo(img, CV_32F);
|
||||
|
||||
// GST components calculation (start)
|
||||
// J = (J11 J12; J12 J22) - GST
|
||||
Mat imgDiffX, imgDiffY, imgDiffXY;
|
||||
Sobel(img, imgDiffX, CV_64F, 1, 0, 3);
|
||||
Sobel(img, imgDiffY, CV_64F, 0, 1, 3);
|
||||
Sobel(img, imgDiffX, CV_32F, 1, 0, 3);
|
||||
Sobel(img, imgDiffY, CV_32F, 0, 1, 3);
|
||||
multiply(imgDiffX, imgDiffY, imgDiffXY);
|
||||
//! [calcJ_header]
|
||||
|
||||
Mat imgDiffXX, imgDiffYY;
|
||||
multiply(imgDiffX, imgDiffX, imgDiffXX);
|
||||
multiply(imgDiffY, imgDiffY, imgDiffYY);
|
||||
|
||||
Mat J11, J22, J12; // J11, J22 and J12 are GST components
|
||||
boxFilter(imgDiffXX, J11, CV_64F, Size(w, w));
|
||||
boxFilter(imgDiffYY, J22, CV_64F, Size(w, w));
|
||||
boxFilter(imgDiffXY, J12, CV_64F, Size(w, w));
|
||||
boxFilter(imgDiffXX, J11, CV_32F, Size(w, w));
|
||||
boxFilter(imgDiffYY, J22, CV_32F, Size(w, w));
|
||||
boxFilter(imgDiffXY, J12, CV_32F, Size(w, w));
|
||||
// GST components calculation (stop)
|
||||
|
||||
// eigenvalue calculation (start)
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @brief You will learn how port an existing algorithm to G-API
|
||||
* @author Dmitry Matveev, dmitry.matveev@intel.com, based
|
||||
* on sample by Karpushin Vladislav, karpushin@ngs.ru
|
||||
*/
|
||||
#include "opencv2/opencv_modules.hpp"
|
||||
#ifdef HAVE_OPENCV_GAPI
|
||||
|
||||
//! [full_sample]
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/gapi.hpp"
|
||||
#include "opencv2/gapi/core.hpp"
|
||||
#include "opencv2/gapi/imgproc.hpp"
|
||||
|
||||
//! [calcGST_proto]
|
||||
void calcGST(const cv::GMat& inputImg, cv::GMat& imgCoherencyOut, cv::GMat& imgOrientationOut, int w);
|
||||
//! [calcGST_proto]
|
||||
|
||||
int main()
|
||||
{
|
||||
int W = 52; // window size is WxW
|
||||
double C_Thr = 0.43; // threshold for coherency
|
||||
int LowThr = 35; // threshold1 for orientation, it ranges from 0 to 180
|
||||
int HighThr = 57; // threshold2 for orientation, it ranges from 0 to 180
|
||||
|
||||
cv::Mat imgIn = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);
|
||||
if (imgIn.empty()) //check whether the image is loaded or not
|
||||
{
|
||||
std::cout << "ERROR : Image cannot be loaded..!!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! [main]
|
||||
// Calculate Gradient Structure Tensor and post-process it for output with G-API
|
||||
cv::GMat in;
|
||||
cv::GMat imgCoherency, imgOrientation;
|
||||
calcGST(in, imgCoherency, imgOrientation, W);
|
||||
|
||||
cv::GMat imgCoherencyBin = imgCoherency > C_Thr;
|
||||
cv::GMat imgOrientationBin = cv::gapi::inRange(imgOrientation, LowThr, HighThr);
|
||||
cv::GMat imgBin = imgCoherencyBin & imgOrientationBin;
|
||||
cv::GMat out = cv::gapi::addWeighted(in, 0.5, imgBin, 0.5, 0.0);
|
||||
|
||||
// Capture the graph into object segm
|
||||
cv::GComputation segm(cv::GIn(in), cv::GOut(out, imgCoherency, imgOrientation));
|
||||
|
||||
// Define cv::Mats for output data
|
||||
cv::Mat imgOut, imgOutCoherency, imgOutOrientation;
|
||||
|
||||
// Run the graph
|
||||
segm.apply(cv::gin(imgIn), cv::gout(imgOut, imgOutCoherency, imgOutOrientation));
|
||||
|
||||
// Normalize extra outputs (out of the graph)
|
||||
cv::normalize(imgOutCoherency, imgOutCoherency, 0, 255, cv::NORM_MINMAX);
|
||||
cv::normalize(imgOutOrientation, imgOutOrientation, 0, 255, cv::NORM_MINMAX);
|
||||
|
||||
cv::imwrite("result.jpg", imgOut);
|
||||
cv::imwrite("Coherency.jpg", imgOutCoherency);
|
||||
cv::imwrite("Orientation.jpg", imgOutOrientation);
|
||||
//! [main]
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [calcGST]
|
||||
//! [calcGST_header]
|
||||
void calcGST(const cv::GMat& inputImg, cv::GMat& imgCoherencyOut, cv::GMat& imgOrientationOut, int w)
|
||||
{
|
||||
auto img = cv::gapi::convertTo(inputImg, CV_32F);
|
||||
auto imgDiffX = cv::gapi::Sobel(img, CV_32F, 1, 0, 3);
|
||||
auto imgDiffY = cv::gapi::Sobel(img, CV_32F, 0, 1, 3);
|
||||
auto imgDiffXY = cv::gapi::mul(imgDiffX, imgDiffY);
|
||||
//! [calcGST_header]
|
||||
|
||||
auto imgDiffXX = cv::gapi::mul(imgDiffX, imgDiffX);
|
||||
auto imgDiffYY = cv::gapi::mul(imgDiffY, imgDiffY);
|
||||
|
||||
auto J11 = cv::gapi::boxFilter(imgDiffXX, CV_32F, cv::Size(w, w));
|
||||
auto J22 = cv::gapi::boxFilter(imgDiffYY, CV_32F, cv::Size(w, w));
|
||||
auto J12 = cv::gapi::boxFilter(imgDiffXY, CV_32F, cv::Size(w, w));
|
||||
|
||||
auto tmp1 = J11 + J22;
|
||||
auto tmp2 = J11 - J22;
|
||||
auto tmp22 = cv::gapi::mul(tmp2, tmp2);
|
||||
auto tmp3 = cv::gapi::mul(J12, J12);
|
||||
auto tmp4 = cv::gapi::sqrt(tmp22 + 4.0*tmp3);
|
||||
|
||||
auto lambda1 = tmp1 + tmp4;
|
||||
auto lambda2 = tmp1 - tmp4;
|
||||
|
||||
imgCoherencyOut = (lambda1 - lambda2) / (lambda1 + lambda2);
|
||||
imgOrientationOut = 0.5*cv::gapi::phase(J22 - J11, 2.0*J12, true);
|
||||
}
|
||||
//! [calcGST]
|
||||
|
||||
//! [full_sample]
|
||||
|
||||
#else
|
||||
#include <iostream>
|
||||
int main()
|
||||
{
|
||||
std::cerr << "This tutorial code requires G-API module to run" << std::endl;
|
||||
}
|
||||
#endif // HAVE_OPECV_GAPI
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* @brief You will learn how port an existing algorithm to G-API
|
||||
* @author Dmitry Matveev, dmitry.matveev@intel.com, based
|
||||
* on sample by Karpushin Vladislav, karpushin@ngs.ru
|
||||
*/
|
||||
#include "opencv2/opencv_modules.hpp"
|
||||
#ifdef HAVE_OPENCV_GAPI
|
||||
|
||||
//! [full_sample]
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include "opencv2/imgproc.hpp"
|
||||
#include "opencv2/imgcodecs.hpp"
|
||||
#include "opencv2/gapi.hpp"
|
||||
#include "opencv2/gapi/core.hpp"
|
||||
#include "opencv2/gapi/imgproc.hpp"
|
||||
//! [fluid_includes]
|
||||
#include "opencv2/gapi/fluid/core.hpp" // Fluid Core kernel library
|
||||
#include "opencv2/gapi/fluid/imgproc.hpp" // Fluid ImgProc kernel library
|
||||
//! [fluid_includes]
|
||||
#include "opencv2/gapi/fluid/gfluidkernel.hpp" // Fluid user kernel API
|
||||
|
||||
//! [calcGST_proto]
|
||||
void calcGST(const cv::GMat& inputImg, cv::GMat& imgCoherencyOut, cv::GMat& imgOrientationOut, int w);
|
||||
//! [calcGST_proto]
|
||||
|
||||
int main()
|
||||
{
|
||||
int W = 52; // window size is WxW
|
||||
double C_Thr = 0.43; // threshold for coherency
|
||||
int LowThr = 35; // threshold1 for orientation, it ranges from 0 to 180
|
||||
int HighThr = 57; // threshold2 for orientation, it ranges from 0 to 180
|
||||
|
||||
cv::Mat imgIn = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);
|
||||
if (imgIn.empty()) //check whether the image is loaded or not
|
||||
{
|
||||
std::cout << "ERROR : Image cannot be loaded..!!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//! [main]
|
||||
// Calculate Gradient Structure Tensor and post-process it for output with G-API
|
||||
cv::GMat in;
|
||||
cv::GMat imgCoherency, imgOrientation;
|
||||
calcGST(in, imgCoherency, imgOrientation, W);
|
||||
|
||||
auto imgCoherencyBin = imgCoherency > C_Thr;
|
||||
auto imgOrientationBin = cv::gapi::inRange(imgOrientation, LowThr, HighThr);
|
||||
auto imgBin = imgCoherencyBin & imgOrientationBin;
|
||||
cv::GMat out = cv::gapi::addWeighted(in, 0.5, imgBin, 0.5, 0.0);
|
||||
|
||||
// Capture the graph into object segm
|
||||
cv::GComputation segm(cv::GIn(in), cv::GOut(out, imgCoherency, imgOrientation));
|
||||
|
||||
// Define cv::Mats for output data
|
||||
cv::Mat imgOut, imgOutCoherency, imgOutOrientation;
|
||||
|
||||
//! [kernel_pkg_proper]
|
||||
//! [kernel_pkg]
|
||||
// Prepare the kernel package and run the graph
|
||||
cv::gapi::GKernelPackage fluid_kernels = cv::gapi::combine // Define a custom kernel package:
|
||||
(cv::gapi::core::fluid::kernels(), // ...with Fluid Core kernels
|
||||
cv::gapi::imgproc::fluid::kernels(), // ...and Fluid ImgProc kernels
|
||||
cv::unite_policy::KEEP);
|
||||
//! [kernel_pkg]
|
||||
//! [kernel_hotfix]
|
||||
fluid_kernels.remove<cv::gapi::imgproc::GBoxFilter>(); // Remove Fluid Box filter as unsuitable,
|
||||
// G-API will fall-back to OpenCV there.
|
||||
//! [kernel_hotfix]
|
||||
//! [kernel_pkg_use]
|
||||
segm.apply(cv::gin(imgIn), // Input data vector
|
||||
cv::gout(imgOut, imgOutCoherency, imgOutOrientation), // Output data vector
|
||||
cv::compile_args(fluid_kernels)); // Kernel package to use
|
||||
//! [kernel_pkg_use]
|
||||
//! [kernel_pkg_proper]
|
||||
|
||||
// Normalize extra outputs (out of the graph)
|
||||
cv::normalize(imgOutCoherency, imgOutCoherency, 0, 255, cv::NORM_MINMAX);
|
||||
cv::normalize(imgOutOrientation, imgOutOrientation, 0, 255, cv::NORM_MINMAX);
|
||||
|
||||
cv::imwrite("result.jpg", imgOut);
|
||||
cv::imwrite("Coherency.jpg", imgOutCoherency);
|
||||
cv::imwrite("Orientation.jpg", imgOutOrientation);
|
||||
//! [main]
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [calcGST]
|
||||
//! [calcGST_header]
|
||||
void calcGST(const cv::GMat& inputImg, cv::GMat& imgCoherencyOut, cv::GMat& imgOrientationOut, int w)
|
||||
{
|
||||
auto img = cv::gapi::convertTo(inputImg, CV_32F);
|
||||
auto imgDiffX = cv::gapi::Sobel(img, CV_32F, 1, 0, 3);
|
||||
auto imgDiffY = cv::gapi::Sobel(img, CV_32F, 0, 1, 3);
|
||||
auto imgDiffXY = cv::gapi::mul(imgDiffX, imgDiffY);
|
||||
//! [calcGST_header]
|
||||
|
||||
auto imgDiffXX = cv::gapi::mul(imgDiffX, imgDiffX);
|
||||
auto imgDiffYY = cv::gapi::mul(imgDiffY, imgDiffY);
|
||||
|
||||
auto J11 = cv::gapi::boxFilter(imgDiffXX, CV_32F, cv::Size(w, w));
|
||||
auto J22 = cv::gapi::boxFilter(imgDiffYY, CV_32F, cv::Size(w, w));
|
||||
auto J12 = cv::gapi::boxFilter(imgDiffXY, CV_32F, cv::Size(w, w));
|
||||
|
||||
auto tmp1 = J11 + J22;
|
||||
auto tmp2 = J11 - J22;
|
||||
auto tmp22 = cv::gapi::mul(tmp2, tmp2);
|
||||
auto tmp3 = cv::gapi::mul(J12, J12);
|
||||
auto tmp4 = cv::gapi::sqrt(tmp22 + 4.0*tmp3);
|
||||
|
||||
auto lambda1 = tmp1 + tmp4;
|
||||
auto lambda2 = tmp1 - tmp4;
|
||||
|
||||
imgCoherencyOut = (lambda1 - lambda2) / (lambda1 + lambda2);
|
||||
imgOrientationOut = 0.5*cv::gapi::phase(J22 - J11, 2.0*J12, true);
|
||||
}
|
||||
//! [calcGST]
|
||||
|
||||
//! [full_sample]
|
||||
|
||||
#else
|
||||
#include <iostream>
|
||||
int main()
|
||||
{
|
||||
std::cerr << "This tutorial code requires G-API module to run" << std::endl;
|
||||
}
|
||||
#endif // HAVE_OPECV_GAPI
|
||||
Reference in New Issue
Block a user