Skip to content

Instantly share code, notes, and snippets.

@RobertApikyan
Created October 18, 2021 12:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RobertApikyan/c285a339bb10ef7b70ba004329ee96ce to your computer and use it in GitHub Desktop.
Save RobertApikyan/c285a339bb10ef7b70ba004329ee96ce to your computer and use it in GitHub Desktop.
//
// smart_capture.cpp
// Runner
//
// Created by Kim Henneken on 28.04.21.
//
#include "smart_capture.hpp"
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
#include "opencv2/calib3d.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features2d.hpp"
#include <thread>
#include <future>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
Mat filter_image(Mat image)
{
cvtColor(image, image, COLOR_RGB2GRAY);
return image;
}
ExtractedFeatures extract_features(Mat mask_template, Mat Template, int nfeatures)
{
Mat template_filtered = filter_image(Template);
Ptr<SIFT> detector = SIFT::create(nfeatures);
std::vector<KeyPoint> kp2;
Mat des2;
detector->detectAndCompute(template_filtered, mask_template, kp2, des2);
ExtractedFeatures extractedFeatures;
extractedFeatures.des2 = des2;
extractedFeatures.kp2 = kp2;
return extractedFeatures;
}
PreparedTemplate prepare_templates(int nfeatures, double ro, Mat MaskTemplate, Mat Template)
{
int h = MaskTemplate.size().height;
int w = MaskTemplate.size().width;
cv::resize(MaskTemplate, MaskTemplate, cv::Size(w * ro, h * ro));
cv::resize(Template, Template, cv::Size(w * ro, h * ro));
Size template_shape = Template.size();
// Mat template_image = Template.setTo(Scalar().all(255.0));
auto future = std::async(extract_features, MaskTemplate, Template, nfeatures);
ExtractedFeatures extracted_features = future.get();
PreparedTemplate preparedTemplate;
preparedTemplate.template_shape = template_shape;
preparedTemplate.des2 = extracted_features.des2;
preparedTemplate.kp2 = extracted_features.kp2;
preparedTemplate.Template = Template;
preparedTemplate.mask_template = MaskTemplate;
return preparedTemplate;
}
StabilisedCard stabilise_card(Mat frame, int min_matches, int nfeatures, std::vector<KeyPoint> kp2, Mat des2, std::vector<int> rect_cords, Size template_shape, String path)
{
cv::Rect rect = cv::Rect(rect_cords.at(0), rect_cords.at(2), rect_cords.at(1) - rect_cords.at(0), rect_cords.at(3) - rect_cords.at(2));
Mat img1 = Mat(frame, rect);
Mat mask1 = img1.clone().setTo(Scalar().all(255.0));
mask1.convertTo(mask1, CV_8U);
double S = mask1.size().height * mask1.size().width;
double height = template_shape.height;
double width = template_shape.width;
double standard = width * height;
double H = img1.size().height;
double W = img1.size().width;
double ratio = pow((S / standard), 0.5);
Size sz = Size(W / ratio, H / ratio);
cv::resize(img1, img1, sz);
cv::resize(mask1, mask1, sz);
mask1.setTo(Scalar().all(10));
Mat filtered_img1 = filter_image(img1);
// cv::imwrite(path, mask1);
Ptr<SIFT> detector = SIFT::create(nfeatures);
std::vector<KeyPoint> kp1;
Mat des1;
detector->detectAndCompute(filtered_img1, noArray(), kp1, des1);
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE);
std::vector<std::vector<DMatch>> knn_matches;
matcher->knnMatch(des1, des2, knn_matches, 2);
std::vector<DMatch> good_matches;
for (size_t i = 0; i < knn_matches.size(); i++)
{
if (knn_matches[i][0].distance < 0.7 * knn_matches[i][1].distance)
{
good_matches.push_back(knn_matches[i][0]);
}
}
StabilisedCard stabilisiedCard;
if (good_matches.size() > min_matches)
{
stabilisiedCard.alignment_quality = (double)good_matches.size() / (double)kp2.size();
return stabilisiedCard;
}
stabilisiedCard.alignment_quality = 0;
return stabilisiedCard;
}
double SmartCapture::smart_capture(Mat canvas, Mat temp, Mat maskTemplate, String type, String min_matches, String card_nfeatures, String alignment_quality, String ro)
{
int min_matches2 = stoi(min_matches);
;
int card_nfeatures2 = stoi(card_nfeatures);
;
int template_nfeatures = 5000;
double ro2 = atof(ro.c_str());
std::vector<double> rectangle;
Mat cap = canvas;
// rectangle = {0.15, 0.85, 0.05, 0.95};
// rectangle = {0.075, 0.925, 0.3 / 3, 1.1 / 3};
rectangle = {0.0, 1.0, 0.0, 1.0};
PreparedTemplate Template = prepare_templates(template_nfeatures, ro2, maskTemplate, temp);
int h = cap.size().height;
int w = cap.size().width;
std::vector<int> rect_coords = {(int)round(w * rectangle.at(0)), (int)round(w * rectangle.at(1)), (int)round(h * rectangle.at(2)), (int)round(h * rectangle.at(3))};
// cvtColor( cap, cap, COLOR_RGB2GRAY );
// cap = filter_image(cap);
auto future = std::async(stabilise_card, cap, min_matches2, card_nfeatures2, Template.kp2, Template.des2, rect_coords, Template.template_shape, type);
StabilisedCard stabilised_card = future.get();
return stabilised_card.alignment_quality;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment