diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 26a0b75..59929ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ Get started with contributing to the OpenCV Catalogue -## For Developers +## For Developers 🧑‍💻 ### Prerequisites for building the source and contributing to the project @@ -18,9 +18,7 @@ Get started with contributing to the OpenCV Catalogue - - -## Contributing +## Contributing 🙌 Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. @@ -32,7 +30,23 @@ Contributions are what make the open source community such an amazing place to b -## Report bugs using Github's [issues](https://github.com/JairajJangle/OpenCV-Catalogue/issues) +### How do I add a new OpenCV Operation? 🤔 + +1. Create file in OpenCVFunction +2. Inherit the class from `BaseConfigWidget` +3. Assign operationName and moreInfoLink in contructor +4. Override `getProcessedImage(...)` with exception handling +5. Override `initWidget()` and populate `BaseConfigWidget::vBox` with parameter adjustment widgets +6. Super call to `BaseConfigWidget::initWidget()` in the end of overriden `initWidget()` +7. In overriden `getProcessedImage(...)` get parameter values from widgets and apply to the OpenCV operation. +8. Return the processed image from `getProcessedImage(...)` +9. Now, in mainwindow.h, import and add Operation Code for the newly added operation in `OPCodes` enum. +10. In mainwindow.cpp, add case for the new `OPCodes` value in `addOperation(...)`, append the object of the new operation to `baseConfigWidgetChain`. +11. Done, that's it. The new operation should be available in he UI. 🎉 + + + +## Report bugs using Github's [issues](https://github.com/JairajJangle/OpenCV-Catalogue/issues) 🐞 We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/JairajJangle/OpenCV-Catalogue/issues/new/choose); it's that easy! @@ -54,6 +68,6 @@ People *love* thorough bug reports. I'm not even kidding. -## License +## License 📜 By contributing, you agree that your contributions will be licensed under its GNU GPLv3 License. \ No newline at end of file diff --git a/OpenCVFunction/contours.h b/OpenCVFunction/contours.h index d9b8e88..56a33d3 100644 --- a/OpenCVFunction/contours.h +++ b/OpenCVFunction/contours.h @@ -53,12 +53,12 @@ class Contours : public BaseConfigWidget prevOffsetText = currentOffsetText; } - /// Find contours + // Find contours cv::findContours(inputImage, contours, hierarchy, mode, method, begin); - /// Draw contours + // Draw contours cv::Mat drawing = cv::Mat::zeros(inputImage.size(), CV_8UC3); for(unsigned int i = 0; i < contours.size(); i++) { diff --git a/OpenCVFunction/warpaffine.h b/OpenCVFunction/warpaffine.h new file mode 100644 index 0000000..425a0e5 --- /dev/null +++ b/OpenCVFunction/warpaffine.h @@ -0,0 +1,85 @@ +/* OpenCV Catalogue is a desktop GUI application to showcase some OpenCV functions + * and parameter adjustment using controls in GUI. + * Copyright (C) 2020 Jairaj Jangle + * + * This file is part of OpenCV Catalogue. + * + * OpenCV Catalogue is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OpenCV Catalogue is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenCV Catalogue. If not, see . + */ + +#pragma once + +#include "CustomWidgets/baseconfigwidget.h" + +class WarpAffine : public BaseConfigWidget +{ + Q_OBJECT +public: + WarpAffine() + { + operationName = "Warp Affine"; + moreInfoLink = "https://docs.opencv.org/4.5.2/da/d54/group__imgproc__transform.html#ga0203d9ee5fcd28d40dbc4a1ea4451983"; + initWidget(); + } + + cv::Mat getProcessedImage(cv::Mat inputImage) override try + { + srcTri[0] = cv::Point2f( 0.f, 0.f ); + srcTri[1] = cv::Point2f( inputImage.cols - 1.f, 0.f ); + srcTri[2] = cv::Point2f( 0.f, inputImage.rows - 1.f ); + + dstTri[0] = cv::Point2f( 0.f, inputImage.rows*0.33f ); + dstTri[1] = cv::Point2f( inputImage.cols*0.85f, inputImage.rows*0.25f ); + dstTri[2] = cv::Point2f( inputImage.cols*0.15f, inputImage.rows*0.7f ); + + cv::Mat warpMat = getAffineTransform(srcTri, dstTri); + cv::Mat warpDst = cv::Mat::zeros( + inputImage.rows, + inputImage.cols, + inputImage.type() + ); + warpAffine(inputImage, warpDst, warpMat, warpDst.size()); + + cv::Point center = cv::Point(warpDst.cols/2, warpDst.rows/2); + double angle = -50.0; + double scale = 0.6; + + cv::Mat rotMat = getRotationMatrix2D(center, angle, scale); + + cv::Mat warpRotateDst; + warpAffine(warpDst, warpRotateDst, rotMat, warpDst.size()); + + // TODO: Add Toggle to show warpRotateDst + + return warpDst; + } + catch(cv::Exception& e){ + throw e; + } catch(std::exception& e) { + throw e; + } + catch(...){ + throw std::string("Unknown Exception in ") + + std::string(typeid(this).name()); + } + +private: + cv::Point2f srcTri[3]; + cv::Point2f dstTri[3]; + +void initWidget() override +{ + BaseConfigWidget::initWidget(); +} +}; diff --git a/OpenCV_Catalogue.pro b/OpenCV_Catalogue.pro index 24379c2..036162a 100644 --- a/OpenCV_Catalogue.pro +++ b/OpenCV_Catalogue.pro @@ -67,6 +67,8 @@ SOURCES += \ CustomWidgets/focusawarelineedit.cpp \ Window/AboutDialog/aboutdialog.cpp \ CustomWidgets/HybridSlider/hybridslider.cpp \ + CustomWidgets/DebugImageLayout/debugimagelayout.cpp \ + Window/CVDebugDialog/cvdebugdialog.cpp \ main.cpp \ Window/MainWindow/mainwindow.cpp @@ -85,6 +87,7 @@ HEADERS += \ CustomWidgets/HybridSlider/hybridslider.h \ CustomWidgets/sliderlayout.h \ CustomWidgets/baseconfigwidget.h \ + CustomWidgets/DebugImageLayout/debugimagelayout.h \ OpenCVFunction/backgroundsubtract.h \ OpenCVFunction/bitwiseops.h \ OpenCVFunction/blur.h \ @@ -101,11 +104,13 @@ HEADERS += \ OpenCVFunction/inrange.h \ OpenCVFunction/resize.h \ OpenCVFunction/subimage.h \ + OpenCVFunction/warpaffine.h \ Utils/captureinputsource.h \ Utils/constants.h \ Utils/logger.h \ Utils/utils.h \ Window/AboutDialog/aboutdialog.h \ + Window/CVDebugDialog/cvdebugdialog.h \ Window/MainWindow/mainwindow.h FORMS += \ @@ -113,6 +118,7 @@ FORMS += \ CustomWidgets/ErrorDialog/errordialog.ui \ Window/AboutDialog/aboutdialog.ui \ CustomWidgets/HybridSlider/hybridslider.ui \ + Window/CVDebugDialog/cvdebugdialog.ui \ Window/MainWindow/mainwindow.ui RESOURCES += \ diff --git a/Window/MainWindow/mainwindow.cpp b/Window/MainWindow/mainwindow.cpp index b24d2ac..ddbb886 100644 --- a/Window/MainWindow/mainwindow.cpp +++ b/Window/MainWindow/mainwindow.cpp @@ -253,6 +253,9 @@ void MainWindow::addOperation(OPCodes opCode) case SUB_IMAGE: baseConfigWidgetChain.append(new SubImage()); break; + case WARP_AFFINE: + baseConfigWidgetChain.append(new WarpAffine()); + break; /* * Append other OpenCV Operation Base Config Widgets diff --git a/Window/MainWindow/mainwindow.h b/Window/MainWindow/mainwindow.h index 75aeb62..c33fba2 100644 --- a/Window/MainWindow/mainwindow.h +++ b/Window/MainWindow/mainwindow.h @@ -62,6 +62,7 @@ #include "OpenCVFunction/contours.h" #include "OpenCVFunction/resize.h" #include "OpenCVFunction/subimage.h" +#include "OpenCVFunction/warpaffine.h" // Include all Custom Widgets here #include "Window/AboutDialog/aboutdialog.h" @@ -87,14 +88,14 @@ class MainWindow : public QMainWindow enum OPCodes{NO_OPERATION, COLOR_SPACES, IMAGE_FLIP, COLOR_PICKER, INRANGE, CANNY_EDGE, BLUR, BKG_SUBTRACT, HOUGH_CIRCLES, HOUGH_LINES, HISTOGRAM_CALCULATION, HARRIS_CORNER, ERODE, DILATE, BITWISE_OPS, - CONTOURS, RESIZE, SUB_IMAGE, + CONTOURS, RESIZE, SUB_IMAGE, WARP_AFFINE, /* - * Add all other Enum values before this - * - * To connect OpenCV operation Base Config widget to - * the added OpCodes enum, see MainWindow::addOperation(...) - */ + * Add all other Enum values before this + * + * To connect OpenCV operation Base Config widget to + * the added OpCodes enum, see MainWindow::addOperation(...) + */ NONE /* Corresponds to OPCodes::NO_OPERATION */ }; private slots: