Closed webbbt456 closed 2 years ago
Problem is here:
cv::GIn(in,numDilation,numErosions) numDilation,numErosions
instead of findContours.
Changed code using cv::GScalar type for numDilations and numErosions. The code compiles.
I am trying to allow numDilations and numErosions. to runtime configurable parameters.
How do I convert numDilations and numErosions to int for use in erode3x3 and dilate3x3?
Or should they be sent in as parameters to the lambda (i.e. [](const int numDilations, const int numErosions) {})?
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/imgproc.hpp>
cv::GComputation mGComputation([]() {
cv::GMat in;
cv::GScalar numDilations; // runtime configurable value
cv::GScalar numErosions; // runtime configurable value
int nd(3), ne(3);
// need to convert numDilation to int and store in nd
// need to convert numErosions to int and store in ne
cv::GMat mask(cv::gapi::gaussianBlur(in, cv::Size(11, 11), 0.0));
mask = cv::gapi::erode3x3(mask, ne);
mask = cv::gapi::dilate3x3(mask, nd);
cv::GArray<cv::GArray<cv::Point>> contours = cv::gapi::findContours(mask, cv::RetrievalModes::RETR_EXTERNAL, cv::ContourApproximationModes::CHAIN_APPROX_SIMPLE);
return cv::GComputation(cv::GIn(in,numDilations,numErosions), cv::GOut(contours));
});
const cv::Scalar white(cv::Scalar(255));
int main(int argc, char** argv)
{
cv::Scalar nDilations(3), nErosions(3);
int rw(60), rh(40), ofs(50), lw(1);
int x(ofs), y(ofs),i;
cv::Mat input(cv::Mat::zeros(640, 480, CV_8UC1));
for (i = 0; i < 3; i++) {
cv::rectangle(input, cv::Rect(x, y, rw, rh), white, lw, cv::FILLED);
x += rw + ofs;
y += rh + ofs;
}
std::vector<std::vector<cv::Point>> contours;
mGComputation.apply(cv::gin(input,nDilations,nErosions),cv::gout(contours));
if (contours.empty()) {
std::cout << "No Contours found." << std::endl;
} else {
std::cout << "Found " << contours.size() << " contours." << std::endl;
}
return 0;
}
How do I convert numDilations and numErosions to int for use in erode3x3 and dilate3x3?
They are usually constants of CV algorithms. Not a computed parameters.
Instead of creation of global pipeline you could create a function with numDilations and numErosions parameters and return the related pipeline with specified values. Check sample code.
Thanks for your help. I have working code as an example now.
Is it possible to convert the contours to rectangles in the lambda? cv::gapi::boundingRect only takes one contour, not a list of contours.
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/imgproc.hpp>
#include <opencv2/highgui.hpp>
#ifdef _DEBUG
#pragma comment(lib, "opencv_highgui455d.lib")
#else
#pragma comment(lib, "opencv_highgui455.lib")
#endif
cv::GComputation CreateGComputation(int nErrosions, int nDilations) {
return cv::GComputation([nErrosions, nDilations]() {
cv::GMat in;
cv::GMat mask(cv::gapi::gaussianBlur(in, cv::Size(11, 11), 0.0));
mask = cv::gapi::erode3x3(mask, nErrosions);
mask = cv::gapi::dilate3x3(mask, nDilations);
cv::GArray<cv::GArray<cv::Point>> contours = cv::gapi::findContours(mask, cv::RetrievalModes::RETR_EXTERNAL, cv::ContourApproximationModes::CHAIN_APPROX_SIMPLE);
// Is it possible to convert the contours to bounding rectangles here?
// cv:GArray<cv::Rect> bboxes = cv::gapi::????(contours);
// return cv::GComputation(cv::GIn(in), cv::GOut(bboxes));
return cv::GComputation(cv::GIn(in), cv::GOut(contours));
});
}
const cv::Scalar white(cv::Scalar(255));
const cv::Scalar black(cv::Scalar(0));
const cv::Scalar gray(cv::Scalar(175));
int main(int argc, char** argv)
{
int nDilations{ 3 }, nErosions{ 3 };
int rw(60), rh(40), ofs(50), lw(1),iw(640),ih(480);
int x(ofs), y(ofs), i;
cv::Rect bounding;
cv::Mat img(ih, iw, CV_8UC1, black);
cv::GComputation mGComputation = CreateGComputation(nErosions, nDilations);
for (i = 0; i < 3; i++) {
cv::Rect rr(x, y, rw, rh);
cv::rectangle(img, rr, white, cv::FILLED);
x += rw + ofs;
y += rh + ofs;
}
std::vector<std::vector<cv::Point>> contours;
mGComputation.apply(cv::gin(img), cv::gout(contours));
if (contours.empty()) {
std::cout << "No Contours found." << std::endl;
} else {
std::cout << "Found " << contours.size() << " contours." << std::endl;
for (auto c : contours) {
bounding = cv::boundingRect(c);
cv::rectangle(img, bounding, gray, 3);
}
char win1[] = "Contour Image";
cv::imshow(win1, img);
cv::moveWindow(win1, iw, 200);
cv::waitKey(0);
}
mGComputation.apply(cv::gin(img), cv::gout(contours));
if (contours.empty()) {
std::cout << "No Contours found." << std::endl;
} else {
std::cout << "Found " << contours.size() << " contours." << std::endl;
for (auto c : contours) {
bounding = cv::boundingRect(c);
cv::rectangle(img, bounding, gray, 3);
}
char win2[] = "Contour Image 2";
cv::imshow(win2, img);
cv::moveWindow(win2, iw*2, 200);
cv::waitKey(0);
}
return 0;
}
Thanks again for your help. I have figured out the last piece of the puzzle.
#include <iostream>
#include <functional>
#include <unordered_map>
#include <utility>
#include <vector>
#include <opencv2/highgui.hpp>
#include "opencv2/gapi/cpu/gcpukernel.hpp"
#ifdef _DEBUG
#pragma comment(lib, "opencv_highgui455d.lib")
#else
#pragma comment(lib, "opencv_highgui455.lib")
#endif
namespace custom {
G_API_OP(ToBoundingRects, <cv::GArray<cv::Rect>(cv::GArray<cv::GArray<cv::Point>>)>, "custom.fd_ToBoundingRects") {
static cv::GArrayDesc outMeta(const cv::GArrayDesc&) {
// This function is required for G-API engine to figure out
// what the output format is, given the input parameters.
// Since the output is an array (with a specific type),
// there's nothing to describe.
return cv::empty_array_desc();
}
};
GAPI_OCV_KERNEL(OCVToBoundingRects, ToBoundingRects) {
static void run(const std::vector<std::vector<cv::Point>> &in_contours,
std::vector<cv::Rect> &out_boundingRects) {
out_boundingRects.clear();
cv::Rect br;
for (auto c : in_contours) {
br = cv::boundingRect(c);
out_boundingRects.push_back(br);
}
}
};
} // namespace custom
cv::GComputation CreateGComputation(int nErrosions, int nDilations) {
return cv::GComputation([nErrosions, nDilations]() {
cv::GMat in;
cv::GMat mask(cv::gapi::gaussianBlur(in, cv::Size(11, 11), 0.0));
mask = cv::gapi::erode3x3(mask, nErrosions);
mask = cv::gapi::dilate3x3(mask, nDilations);
cv::GArray<cv::GArray<cv::Point>> contours = cv::gapi::findContours(mask, cv::RetrievalModes::RETR_EXTERNAL, cv::ContourApproximationModes::CHAIN_APPROX_SIMPLE);
cv::GArray<cv::Rect> boundingRects = custom::ToBoundingRects::on(contours);
return cv::GComputation(cv::GIn(in), cv::GOut(boundingRects));
});
}
const cv::Scalar white(cv::Scalar(255));
const cv::Scalar black(cv::Scalar(0));
const cv::Scalar gray(cv::Scalar(175));
int main(int argc, char** argv)
{
int nDilations{ 3 }, nErosions{ 3 };
int rw(60), rh(40), ofs(50), lw(1),iw(640),ih(480);
int x(ofs), y(ofs), i;
cv::Mat img(ih, iw, CV_8UC1, black);
cv::gapi::GKernelPackage kernels = cv::gapi::kernels<custom::OCVToBoundingRects>();
cv::GComputation mGComputation = CreateGComputation(nErosions, nDilations);
for (i = 0; i < 3; i++) {
cv::Rect rr(x, y, rw, rh);
cv::rectangle(img, rr, white, cv::FILLED);
x += rw + ofs;
y += rh + ofs;
}
std::vector<cv::Rect> boundingRects;
mGComputation.apply(cv::gin(img), cv::gout(boundingRects),cv::compile_args(kernels));
if (boundingRects.empty()) {
std::cout << "No Bounding Rectangles found." << std::endl;
} else {
std::cout << "Found " << boundingRects.size() << " Bounding Rectangles." << std::endl;
for (auto bounding : boundingRects) {
cv::rectangle(img, bounding, gray, 3);
}
char win1[] = "Bounding Rectangle Image 1";
cv::imshow(win1, img);
cv::moveWindow(win1, iw, 200);
cv::waitKey(0);
}
x -= (ofs + rw);
y = ofs;
for (i = 0; i < 3; i++) {
cv::Rect rr(x, y, rw, rh);
cv::rectangle(img, rr, white, cv::FILLED);
x += rw + ofs;
y += rh + ofs;
}
mGComputation.apply(cv::gin(img), cv::gout(boundingRects),cv::compile_args(kernels));
if (boundingRects.empty()) {
std::cout << "No Bounding Rectangles found." << std::endl;
} else {
std::cout << "Found " << boundingRects.size() << " Bounding Rectangles." << std::endl;
for (auto bounding : boundingRects) {
cv::rectangle(img, bounding, gray, 3);
}
char win2[] = "Bounding Rectangle Image 2";
cv::imshow(win2, img);
cv::moveWindow(win2, iw*2, 200);
cv::waitKey(0);
}
return 0;
}
System information (version)
Detailed description
I have compiled version 4.5.5 on windows with Visual Studio. I am unable to compile code dealing with GAPI that calls findContours and returns the contours. In my example I have a conditional compilation that returns a GMat instead of contours, the code compiles.
Compiler Error from VS (Error List Window) Error C2338 Type not found testGAPI opencv\include\opencv2\gapi\util\variant.hpp 37
'''
Compiler Warning from VS (Output Window) 1>opencv\include\opencv2\gapi\util\variant.hpp(37,56): error C2338: Type not found 1>opencv\include\opencv2\gapi\util\variant.hpp(31): message : see reference to class template instantiation 'cv::util::detail::type_list_index_helper<5,Target,cv::detail::GOpaqueU>' being compiled 1> with 1> [ 1> Target=int 1> ] 1>opencv\include\opencv2\gapi\util\variant.hpp(31): message : see reference to class template instantiation 'cv::util::detail::type_list_index_helper<4,Target,cv::detail::GArrayU,cv::detail::GOpaqueU>' being compiled 1> with 1> [ 1> Target=int 1> ] 1>opencv\include\opencv2\gapi\util\variant.hpp(31): message : see reference to class template instantiation 'cv::util::detail::type_list_index_helper<3,Target,cv::GScalar,cv::detail::GArrayU,cv::detail::GOpaqueU>' being compiled 1> with 1> [ 1> Target=int 1> ] 1>opencv\include\opencv2\gapi\util\variant.hpp(31): message : see reference to class template instantiation 'cv::util::detail::type_list_index_helper<2,Target,cv::GFrame,cv::GScalar,cv::detail::GArrayU,cv::detail::GOpaqueU>' being compiled 1> with 1> [ 1> Target=int 1> ] 1>opencv\include\opencv2\gapi\util\variant.hpp(31): message : see reference to class template instantiation 'cv::util::detail::type_list_index_helper<1,Target,cv::GMatP,cv::GFrame,cv::GScalar,cv::detail::GArrayU,cv::detail::GOpaqueU>' being compiled 1> with 1> [ 1> Target=int 1> ] 1>opencv\include\opencv2\gapi\util\variant.hpp(45): message : see reference to class template instantiation 'cv::util::detail::type_list_index_helper<0,Target,cv::GMat,cv::GMatP,cv::GFrame,cv::GScalar,cv::detail::GArrayU,cv::detail::GOpaqueU>' being compiled 1> with 1> [ 1> Target=int 1> ] 1>opencv\include\opencv2\gapi\util\variant.hpp(351): message : see reference to class template instantiation 'cv::util::type_list_index<int,cv::GMat,cv::GMatP,cv::GFrame,cv::GScalar,cv::detail::GArrayU,cv::detail::GOpaqueU>' being compiled 1>opencv\include\opencv2\gapi\gproto.hpp(50): message : see reference to function template instantiation 'cv::util::variant<cv::GMat,cv::GMatP,cv::GFrame,cv::GScalar,cv::detail::GArrayU,cv::detail::GOpaqueU>::variant<_Ty,void>(T &&)' being compiled 1> with 1> [ 1> _Ty=int, 1> T=int 1> ] 1>opencv\include\opencv2\gapi\gproto.hpp(51): message : see reference to function template instantiation 'cv::util::variant<cv::GMat,cv::GMatP,cv::GFrame,cv::GScalar,cv::detail::GArrayU,cv::detail::GOpaqueU>::variant<_Ty,void>(T &&)' being compiled 1> with 1> [ 1> _Ty=int, 1> T=int 1> ] 1>opencv\include\opencv2\gapi\gproto.hpp(97): message : see reference to function template instantiation 'cv::GProtoArgs cv::detail::packArgs<cv::GMat,int,int>(cv::GMat,int,int)' being compiled 1>testGAPI\testGAPI.cpp(44): message : see reference to function template instantiation 'cv::GProtoInputArgs cv::GIn<cv::GMat&,int&,int&>(cv::GMat &,int &,int &)' being compiled 1>Done building project "testGAPI.vcxproj" -- FAILED.
'''
Steps to reproduce