I have a small program in C ++ that can recognize objects in an image. I also have a REST API (developed with express.js runtime on NodeJS) that downloads an image (by sending mobile) in a specific folder.
The idea is how to link the C ++ file (main.cpp) with NodeJS! that is to say, when an image is sent to the server it will then download the NodeJS must run the C ++ file (main.cpp) to know the object in the image sent by mobile. Then he sent the response to mobile terminal in the form of the same picture framing the found object.
thanks for the help
-code C++:
//main.cpp
#include "mainwindow.h"
#include <QApplication>
#include "opencv2/opencv.hpp"
#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include <opencv2/features2d.hpp>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/xfeatures2d/nonfree.hpp"
#include "opencv2/xfeatures2d.hpp"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Here the processing class: mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "opencv2/opencv.hpp"
#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include <opencv2/features2d.hpp>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/xfeatures2d/nonfree.hpp"
#include "opencv2/xfeatures2d.hpp"
#include "opencv2/imgcodecs.hpp"
using namespace cv;
void readme();
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
cv::Mat img_object = cv::imread("/home/emile/Pictures/jeux.jpg");
cv::Mat img_scene = cv::imread("//home/emile/Pictures/jeux_vectorss.jpg");
int minHessian = 400;
cv::Ptr<Feature2D> detector = xfeatures2d::SIFT::create(minHessian);
std::vector<KeyPoint> keypoints_object, keypoints_scene;
detector->detect(img_object, keypoints_object);
detector->detect(img_scene, keypoints_scene);
//-- Step 2: Calculate descriptors (feature vectors)
Mat descriptors_object, descriptors_scene;
detector->compute( img_object, keypoints_object, descriptors_object );
detector->compute( img_scene, keypoints_scene, descriptors_scene );
//-- Step 3: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_object, descriptors_scene, matches );
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_object.rows; i++ )
{ double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist );
printf("-- Min dist : %f \n", min_dist );
//-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
//BFMatcher good_matcher;
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_object.rows; i++ )
{ if( matches[i].distance < 3*min_dist )
{ good_matches.push_back( matches[i]); }
}
Mat img_matches;
std::vector<char> vec;
drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vec, DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- Localize the object
std::vector<Point2f> obj;
std::vector<Point2f> scene;
for( size_t i = 0; i < good_matches.size(); i++ )
{
//-- Get the keypoints from the good matches
obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
}
Mat H = findHomography( obj, scene, CV_RANSAC );
//-- Get the corners from the image_1 ( the object to be "detected" )
std::vector<Point2f> obj_corners(4);
obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows );
std::vector<Point2f> scene_corners(4);
perspectiveTransform( obj_corners, scene_corners, H);
//-- Draw lines between the corners (the mapped object in the scene - image_2 )
line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners[1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 );
line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0), scene_corners[2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0), scene_corners[3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0), scene_corners[0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
//-- Show detected matches
imshow( " Object detection", img_matches );
waitKey(0);
return ;
}
void readme()
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
MainWindow::~MainWindow()
{
delete ui;
}
MainActivity.java
public class MainActivity extends Activity {
Button imgsel,upload;
ImageView img;
String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img = (ImageView)findViewById(R.id.img);
Ion.getDefault(this).configure().setLogging("ion-sample", Log.DEBUG);
imgsel = (Button)findViewById(R.id.selimg);
upload =(Button)findViewById(R.id.uploadimg);
upload.setVisibility(View.INVISIBLE);
upload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
File f = new File(path);
Future uploading = Ion.with(MainActivity.this)
.load("http://xxx.xxx.xx.xxx:xxxx/uploads")
.setMultipartFile("image",f)
//asJsonObject()
.asString()
.withResponse()
.setCallback(new FutureCallback<Response<String>>() {
@Override
public void onCompleted(Exception e, Response<String> result) {
try {
JSONObject jobj = new JSONObject(result.getResult());
Toast.makeText(getApplicationContext(), jobj.getString("response"), Toast.LENGTH_SHORT).show();
} catch (JSONException e1) {
e1.printStackTrace();
}
}
});
}
});
imgsel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent fintent = new Intent(Intent.ACTION_GET_CONTENT);
fintent.setType("image/*");
try {
startActivityForResult(fintent, 100);
} catch (ActivityNotFoundException e) {
}
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data == null)
return;
switch (requestCode) {
case 100:
if (resultCode == RESULT_OK) {
path = getPathFromURI(data.getData());
img.setImageURI(data.getData());
upload.setVisibility(View.VISIBLE);
}
}
}
private String getPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(getApplicationContext(), contentUri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
}