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
| #include <opencv2/opencv.hpp> #include <iostream> #include <filesystem>
int main() { cv::dnn::Net net = cv::dnn::readNetFromONNX("../mnist.onnx");
cv::Mat image = cv::imread("../images/numbers.jpg"); cv::Mat original = image.clone();
cv::cvtColor(image, image, cv::COLOR_BGR2GRAY); cv::threshold(image, image, 128, 255, cv::THRESH_BINARY_INV); cv::GaussianBlur(image, image, cv::Size(7, 7), 0); cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); cv::dilate(image, image, kernel);
std::vector<std::vector<cv::Point>> contours; cv::findContours(image, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector<std::vector<cv::Point>> digit_contours;
for (const auto &contour : contours) { if (cv::contourArea(contour) > 100) { digit_contours.push_back(contour); } }
for (const auto &contour : digit_contours) { cv::Rect rect = cv::boundingRect(contour);
cv::rectangle(original, rect, cv::Scalar(0, 255, 0), 2);
cv::Mat digit = image(rect);
int padding = std::max(digit.rows, digit.cols) / 6; int padding_top_bottom = (digit.rows >= digit.cols) ? padding : (std::max(digit.rows, digit.cols) - std::min(digit.rows, digit.cols)) / 2 + padding; int padding_left_right = (digit.rows >= digit.cols) ? (std::max(digit.rows, digit.cols) - std::min(digit.rows, digit.cols)) / 2 + padding : padding;
cv::copyMakeBorder(digit, digit, padding_top_bottom, padding_top_bottom, padding_left_right, padding_left_right, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));
cv::Mat blob = cv::dnn::blobFromImage(digit, 1.0 / 255.0, cv::Size(28, 28), cv::Scalar(0.1307 * 255), false, false);
net.setInput(blob);
cv::Mat prob = net.forward();
cv::exp(prob, prob); cv::divide(prob, cv::sum(prob)[0], prob);
cv::Point classIdPoint; double confidence; cv::minMaxLoc(prob.reshape(1, 1), nullptr, &confidence, nullptr, &classIdPoint);
std::cout << std::format("{}, confidence: {}\n", classIdPoint.x, confidence);
cv::putText(original, std::to_string(classIdPoint.x), rect.tl(), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2);
cv::imshow("digit", digit); cv::waitKey(0); }
cv::imshow("image", original); cv::waitKey(0); cv::destroyAllWindows();
return 0; }
|