File size: 4,155 Bytes
07ad80f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <string>
#include <cmath>
#include <vector>
using namespace cv;
using namespace cv::dnn;
using namespace std;
class Dexined {
public:
Dexined(const string& modelPath) {
loadModel(modelPath);
}
// Function to set up the input image and process it
void processFrame(const Mat& image, Mat& result) {
Mat blob = blobFromImage(image, 1.0, Size(512, 512), Scalar(103.5, 116.2, 123.6), false, false, CV_32F);
net.setInput(blob);
applyDexined(image, result);
}
private:
Net net;
// Load Model
void loadModel(const string modelPath) {
net = readNetFromONNX(modelPath);
net.setPreferableBackend(DNN_BACKEND_DEFAULT);
net.setPreferableTarget(DNN_TARGET_CPU);
}
// Function to apply sigmoid activation
static void sigmoid(Mat& input) {
exp(-input, input); // e^-input
input = 1.0 / (1.0 + input); // 1 / (1 + e^-input)
}
// Function to process the neural network output to generate edge maps
static pair<Mat, Mat> postProcess(const vector<Mat>& output, int height, int width) {
vector<Mat> preds;
preds.reserve(output.size());
for (const Mat &p : output) {
Mat img;
Mat processed;
if (p.dims == 4 && p.size[0] == 1 && p.size[1] == 1) {
processed = p.reshape(0, {p.size[2], p.size[3]});
} else {
processed = p.clone();
}
sigmoid(processed);
normalize(processed, img, 0, 255, NORM_MINMAX, CV_8U);
resize(img, img, Size(width, height));
preds.push_back(img);
}
Mat fuse = preds.back();
Mat ave = Mat::zeros(height, width, CV_32F);
for (Mat &pred : preds) {
Mat temp;
pred.convertTo(temp, CV_32F);
ave += temp;
}
ave /= static_cast<float>(preds.size());
ave.convertTo(ave, CV_8U);
return {fuse, ave};
}
// Function to apply the Dexined model
void applyDexined(const Mat& image, Mat& result) {
int originalWidth = image.cols;
int originalHeight = image.rows;
vector<Mat> outputs;
net.forward(outputs);
pair<Mat, Mat> res = postProcess(outputs, originalHeight, originalWidth);
result = res.first; // or res.second for average edge map
}
};
int main(int argc, char** argv) {
const string about =
"This sample demonstrates edge detection with dexined edge detection techniques.\n\n";
const string keys =
"{ help h | | Print help message. }"
"{ input i | | Path to input image or video file. Skip this argument to capture frames from a camera.}"
"{ model | edge_detection_dexined_2024sep.onnx | Path to the dexined.onnx model file }";
CommandLineParser parser(argc, argv, keys);
if (parser.has("help"))
{
cout << about << endl;
parser.printMessage();
return -1;
}
parser = CommandLineParser(argc, argv, keys);
string model = parser.get<String>("model");
parser.about(about);
VideoCapture cap;
if (parser.has("input"))
cap.open(samples::findFile(parser.get<String>("input")));
else
cap.open(0);
namedWindow("Input", WINDOW_AUTOSIZE);
namedWindow("Output", WINDOW_AUTOSIZE);
moveWindow("Output", 200, 0);
// Create an instance of Dexined
Dexined dexined(model);
Mat image;
for (;;){
cap >> image;
if (image.empty())
{
cout << "Press any key to exit" << endl;
waitKey();
break;
}
Mat result;
dexined.processFrame(image, result);
imshow("Input", image);
imshow("Output", result);
int key = waitKey(1);
if (key == 27 || key == 'q')
{
break;
}
}
destroyAllWindows();
return 0;
}
|