mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-20 21:40:49 +08:00
Fixed a bug where params.PFmode = true caused incorrect edge detection results. Updated edge_drawing.py to support the new EDColor feature. Created a new edge_drawing_demo.cpp for demonstrating the EDColor feature. Updated ximgproc.bib to include references for EDColor. Added tests for PFmode and EDColor in test_fld.cpp. Added CV_WRAP to Params::read and Params::write functions to expose them to Python bindings. the class NFALUT uses the code from original ED code
186 lines
6.1 KiB
C++
186 lines
6.1 KiB
C++
/* edge_drawing.cpp
|
|
|
|
This example illustrates how to use cv.ximgproc.EdgeDrawing class.
|
|
|
|
It uses the OpenCV library to load an image, and then use the EdgeDrawing class
|
|
to detect edges, lines, and ellipses. The detected features are then drawn and displayed.
|
|
|
|
The main loop allows the user changing parameters of EdgeDrawing by pressing following keys:
|
|
|
|
to toggle the grayscale conversion press 'space' key
|
|
to increase MinPathLength value press '/' key
|
|
to decrease MinPathLength value press '*' key
|
|
to increase MinLineLength value press '+' key
|
|
to decrease MinLineLength value press '-' key
|
|
to toggle NFAValidation value press 'n' key
|
|
to toggle PFmode value press 'p' key
|
|
to save parameters to file press 's' key
|
|
to load parameters from file press 'l' key
|
|
|
|
The program exits when the Esc key is pressed.
|
|
*/
|
|
|
|
#include <opencv2/imgproc.hpp>
|
|
#include <opencv2/highgui.hpp>
|
|
#include <opencv2/ximgproc.hpp>
|
|
#include <iostream>
|
|
|
|
void EdgeDrawingDemo(const cv::Mat src, cv::Ptr<cv::ximgproc::EdgeDrawing> ed, bool convert_to_gray);
|
|
|
|
void EdgeDrawingDemo(const cv::Mat src, cv::Ptr<cv::ximgproc::EdgeDrawing> ed, bool convert_to_gray)
|
|
{
|
|
cv::Mat ssrc = cv::Mat::zeros(src.size(), src.type());
|
|
cv::Mat lsrc = src.clone();
|
|
cv::Mat esrc = src.clone();
|
|
|
|
std::cout << std::endl << "convert_to_gray: " << convert_to_gray << std::endl;
|
|
std::cout << "MinPathLength: " << ed->params.MinPathLength << std::endl;
|
|
std::cout << "MinLineLength: " << ed->params.MinLineLength << std::endl;
|
|
std::cout << "PFmode: " << ed->params.PFmode << std::endl;
|
|
std::cout << "NFAValidation: " << ed->params.NFAValidation << std::endl;
|
|
|
|
cv::TickMeter tm;
|
|
tm.start();
|
|
|
|
cv::Mat img_to_detect;
|
|
|
|
if (convert_to_gray)
|
|
{
|
|
cv::cvtColor(src, img_to_detect, cv::COLOR_BGR2GRAY);
|
|
}
|
|
else
|
|
{
|
|
img_to_detect = src;
|
|
}
|
|
|
|
cv::imshow("source image", img_to_detect);
|
|
|
|
tm.start();
|
|
|
|
// Detect edges
|
|
ed->detectEdges(img_to_detect);
|
|
|
|
std::vector<std::vector<cv::Point>> segments = ed->getSegments();
|
|
std::vector<cv::Vec4f> lines;
|
|
ed->detectLines(lines);
|
|
std::vector<cv::Vec6d> ellipses;
|
|
ed->detectEllipses(ellipses);
|
|
|
|
tm.stop();
|
|
|
|
cv::RNG& rng = cv::theRNG();
|
|
cv::setRNGSeed(0);
|
|
|
|
// Draw detected edge segments
|
|
for (const auto& segment : segments)
|
|
{
|
|
cv::Scalar color(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
|
|
cv::polylines(ssrc, segment, false, color, 1, cv::LINE_8);
|
|
}
|
|
|
|
cv::imshow("detected edge segments", ssrc);
|
|
|
|
// Draw detected lines
|
|
if (!lines.empty()) // Check if the lines have been found and only then iterate over these and add them to the image
|
|
{
|
|
for (size_t i = 0; i < lines.size(); i++)
|
|
{
|
|
cv::line(lsrc, cv::Point2d(lines[i][0], lines[i][1]), cv::Point2d(lines[i][2], lines[i][3]), cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
|
|
}
|
|
}
|
|
|
|
cv::imshow("detected lines", lsrc);
|
|
|
|
// Draw detected circles and ellipses
|
|
if (!ellipses.empty()) // Check if circles and ellipses have been found and only then iterate over these and add them to the image
|
|
{
|
|
for (const auto& ellipse : ellipses)
|
|
{
|
|
cv::Point center((int)ellipse[0], (int)ellipse[1]);
|
|
cv::Size axes((int)ellipse[2] + (int)ellipse[3], (int)ellipse[2] + (int)ellipse[4]);
|
|
double angle(ellipse[5]);
|
|
cv::Scalar color = (ellipse[2] == 0) ? cv::Scalar(0, 255, 0) : cv::Scalar(0, 0, 255);
|
|
cv::ellipse(esrc, center, axes, angle, 0, 360, color, 1, cv::LINE_AA);
|
|
}
|
|
}
|
|
|
|
cv::imshow("detected circles and ellipses", esrc);
|
|
std::cout << "Total Detection Time : " << tm.getTimeMilli() << "ms." << std::endl;
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
std::string filename = (argc > 1) ? argv[1] : "board.jpg";
|
|
cv::Mat src = cv::imread(cv::samples::findFile(filename));
|
|
|
|
if (src.empty())
|
|
{
|
|
std::cerr << "Error: Could not open or find the image!" << std::endl;
|
|
return -1;
|
|
}
|
|
|
|
cv::Ptr<cv::ximgproc::EdgeDrawing> ed = cv::ximgproc::createEdgeDrawing();
|
|
|
|
// Set parameters (refer to the documentation for all parameters)
|
|
ed->params.MinPathLength = 10; // try changing this value by pressing '/' and '*' keys
|
|
ed->params.MinLineLength = 10; // try changing this value by pressing '+' and '-' keys
|
|
ed->params.PFmode = false; // default value is false, try switching by pressing 'p' key
|
|
ed->params.NFAValidation = true; // default value is true, try switching by pressing 'n' key
|
|
|
|
bool convert_to_gray = true;
|
|
int key = 0;
|
|
|
|
while (key != 27)
|
|
{
|
|
EdgeDrawingDemo(src, ed, convert_to_gray);
|
|
key = cv::waitKey(0);
|
|
|
|
switch (key)
|
|
{
|
|
case 32: // space key
|
|
convert_to_gray = !convert_to_gray;
|
|
break;
|
|
case 'p': // 'p' key
|
|
ed->params.PFmode = !ed->params.PFmode;
|
|
break;
|
|
case 'n': // 'n' key
|
|
ed->params.NFAValidation = !ed->params.NFAValidation;
|
|
break;
|
|
case '+': // '+' key
|
|
ed->params.MinLineLength = std::max(0, ed->params.MinLineLength + 5);
|
|
break;
|
|
case '-': // '-' key
|
|
ed->params.MinLineLength = std::max(0, ed->params.MinLineLength - 5);
|
|
break;
|
|
case '/': // '/' key
|
|
ed->params.MinPathLength += 20;
|
|
break;
|
|
case '*': // '*' key
|
|
ed->params.MinPathLength = std::max(0, ed->params.MinPathLength - 20);
|
|
break;
|
|
case 's': // 's' key
|
|
{
|
|
cv::FileStorage fs("ed-params.xml", cv::FileStorage::WRITE);
|
|
ed->params.write(fs);
|
|
fs.release();
|
|
std::cout << "Parameters saved to ed-params.xml" << std::endl;
|
|
}
|
|
break;
|
|
case 'l': // 'l' key
|
|
{
|
|
cv::FileStorage fs("ed-params.xml", cv::FileStorage::READ);
|
|
if (fs.isOpened())
|
|
{
|
|
ed->params.read(fs.root());
|
|
fs.release();
|
|
std::cout << "Parameters loaded from ed-params.xml" << std::endl;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|