Bonjour à tous,
Je réalise un projet (scolaire) où une partie consiste à détecter un mouvement à partir d'une webcam (branchée sur mon PC) et à allumer une LED branchée sur une carte Arduino. Donc j'aimerais que lorsqu'un mouvement est détecté (je prends 500 à titre d'exemple dans le main.cpp) la LED de la carte Arduino s'allume et s’éteint lorsqu'il n'y pas ou plus de mouvement.
J’utilise pour cela 2 programmes séparément, c'est-à-dire que je lance le programme de détection de mouvement (main.cpp) qui fonctionne avec Open CV. Le programme modifie une variable externe (var) que je réutilise dans le programme Arduino (arduino_command.ino) par l'intermédiaire d'un fichier header (Arduino_command.h).
Le programme main.cpp fonctionne correctement, mais lorsque je lance le programme Arduino, j'obtient l'erreur suivante :
Arduino_command.ino: In function void loop()
Arduino_command.ino: 12: error: expected primary-expression before 'extern
Arduino_command.ino: 12: error: expected `;' before 'extern
Error compiling project sources
Debug build failed for project 'Arduino_command'
Je comprends bien qu'il ne reconnaît pas le mot clé 'extern' pour ce code Arduino :
Arduino_command.ino
#include "Arduino_command.h"
int a = 0;
void setup()
{
pinMode(11, OUTPUT);
}
void loop()
{
a = extern var;
if (a == 1) {
digitalWrite(11, HIGH);
}
else {
digitalWrite(11, LOW);
}
}
Mais lorsque j'enlève le mot clé 'extern', j'ai le message suivant, me disant que la variable 'var' n'est pas définit, alors que je lance avant le programme (main.cpp) qui définit justement cette variable :
Arduino_command.cpp.o*: In function loop
Arduino_command.ino:12: undefined reference to var
Arduino_command.ino:12: undefined reference to var
Error linking for board Arduino Uno
Debug build failed for project 'Arduino_command'
D'ailleurs que je lance le programme 'main.cpp' ou pas cela ne change rien (l'erreur reste la même).
J’utilise une variable externe, car je pense que c'est la façon la plus simple de résoudre ce problème, mais visiblement Arduino n'a pas l'air d'aimer.
Ça fait une semaine que je suis dessus et je n'y arrive pas, j'ai essayer de créer des classes, des fonctions, en les important dans un fichier .ino par l'intermédiaire d'un fichier header (.h), mais je rencontre le même problème.
J'ai aussi regardé les codes proposé sur ce site :
http://aleksandarkrstikj.com/Tracking-a-ball-and-Rotating-Camera-with-OpenCV-and-Arduino/
Mais je ne comprends toujours pas comment je pourrais faire.
Je tiens à préciser que je suis débutant en programmation et surtout en C++, donc il est probablement possible de résoudre ce problème en utilisant des classes, mais même avec les recherches fait sur internet et les tests effectués, je ne vois pas comment faire.
Les 2 fichiers ne sont pas dans le même dossier, car j'utilise Visual Studio 2015 (avec Visual micro pour le programme Arduino) pour les 2 programmes et je dois les placer dans un dossier différents (je crée 2 projets différents). J'ai placé le programme Arduino avec le header dans un dossier 'Arduino_command' (même nom que le projet Arduino) qui se trouve dans le même répertoire que 'main.cpp'.
Voici les codes du 'main.cpp' et du 'Arduino_command.h' pour y voir plus clair :
Arduino_command.h
#ifndef _ARDUINO_COMMAND_h
#define _ARDUINO_COMMAND_h
extern int var;
#endif
main.cpp
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
#include "Arduino-command\test.h"
using namespace cv;
using namespace std;
void addImageToComposition(Mat& composedImage, Mat& image, const bool isGrayscale, const int quarter) {
const auto width = composedImage.size().width;
const auto height = composedImage.size().height;
const auto halfWidth = width / 2;
const auto halfHeight = height / 2;
resize(image, image, Size(halfWidth, halfHeight));
if (isGrayscale) {
cvtColor(image, image, COLOR_GRAY2RGB);
}
Range rowsRange, colsRange;
if (quarter == 1) {
rowsRange = Range(0, halfHeight);
colsRange = Range(halfWidth, width);
}
else if (quarter == 2) {
rowsRange = Range(0, halfHeight);
colsRange = Range(0, halfWidth);
}
else if (quarter == 3) {
rowsRange = Range(halfHeight, height);
colsRange = Range(0, halfWidth);
}
else if (quarter == 4) {
rowsRange = Range(halfHeight, height);
colsRange = Range(halfWidth, width);
}
image.copyTo(Mat(composedImage, rowsRange, colsRange));
}
void uniteRectangles(vector<Rect>& rectangles) {
vector<char> useRectangles(rectangles.size(), 1);
while (true) {
auto wasChange = false;
for (int i = 0; i < rectangles.size(); ++i) {
if (!useRectangles[i]) {
continue;
}
for (int j = i + 1; j < rectangles.size(); ++j) {
if (useRectangles[j] && ((rectangles[i] & rectangles[j]).area() > 0)) {
rectangles[i] |= rectangles[j];
useRectangles[j] = false;
wasChange = true;
}
}
}
if (!wasChange) {
break;
}
}
vector<Rect> resultRectangles;
for (int i = 0; i < rectangles.size(); ++i) {
if (useRectangles[i]) {
resultRectangles.push_back(rectangles[i]);
}
}
rectangles = resultRectangles;
}
int var = 0;
void processVideo() {
VideoCapture capture(0);
Mat cameraImage, blurredImage, blocksImage, contoursImage;
Ptr<BackgroundSubtractorKNN> backgroundSubstructor = createBackgroundSubtractorKNN(10, 400, true);
Mat dilateElement = getStructuringElement(MORPH_RECT, Size(32, 32));
while (true) {
capture.read(cameraImage);
cvtColor(cameraImage, blurredImage, CV_BGR2GRAY);
GaussianBlur(blurredImage, blurredImage, Size(21, 21), 0, 0);
backgroundSubstructor->apply(blurredImage, blurredImage);
threshold(blurredImage, blocksImage, backgroundSubstructor->getShadowValue() + 1, 255, THRESH_BINARY);
dilate(blocksImage, blocksImage, dilateElement, Point(-1, -1), 2);
contoursImage = blocksImage.clone();
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(contoursImage, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
vector<Rect> rectangles;
contoursImage = Mat::zeros(blocksImage.size(), CV_8UC3);
for (int i = 0; i < contours.size(); ++i) {
drawContours(contoursImage, contours, i, Scalar(255, 0, 0), 2, 8, hierarchy, 0);
const auto rect = boundingRect(contours[i]);
if (rect.area() >= 50000) {
rectangles.push_back(rect);
}
if (rect.area() >= 500) {
var = 1;
}
else {
var = 0;
}
}
uniteRectangles(rectangles);
for (const auto& rect : rectangles) {
rectangle(cameraImage, rect, Scalar(0, 255, 0), 8);
}
Mat composedImage(cameraImage.size(), cameraImage.type());
addImageToComposition(composedImage, blurredImage, true, 2);
addImageToComposition(composedImage, blocksImage, true, 1);
addImageToComposition(composedImage, contoursImage, false, 3);
addImageToComposition(composedImage, cameraImage, false, 4);
imshow("Scene", composedImage);
int c = waitKey(30);
}
capture.release();
}
int main(int argc, char* argv[]) {
namedWindow("Scene");
processVideo();
destroyAllWindows();
return EXIT_SUCCESS;
}
Ma question est donc : Comment pourrais je allumer ou éteindre une LED en détectant un mouvement avec Open CV et Arduino ?
Sachant que je suis sous Windows 8.1, j'utilise Visual micro (Arduino 1.0) pour une carte Arduino Uno.
PS : Je précise également que les 2 programmes fonctionnent correctement séparément (quand je mets une autre variable dans le fichier .ino qui est interne à celle-ci), c'est donc un problème de lien entre le main.cpp et le Arduino_command.ino avec le header.
Merci d'avance pour vos réponses.