Commit dfc340d6 authored by Brett's avatar Brett

Add dropdown menu to camera view, add squares.ccp

parent b4498a73
......@@ -136,7 +136,10 @@ CameraDisplay::CameraDisplay(QWidget *parent, int camera_index)
for (int i = 0; i < cameras.size(); ++i) {
m_camera_list->addItem(cameras[i].deviceName(), QVariant::fromValue(i));
}
m_effects_list = new QComboBox(this);
m_effects_list->setMinimumSize(150, 30);
m_effects_list->addItem("None", QVariant::fromValue(0));
m_effects_list->addItem("Squares", QVariant::fromValue(1));
m_converter.setProcessAll(false);
m_capture_thread.start();
m_converter_thread.start();
......@@ -147,12 +150,14 @@ CameraDisplay::CameraDisplay(QWidget *parent, int camera_index)
setLayout(m_layout);
m_layout->addWidget(m_camera_list);
m_layout->addWidget(m_effects_list);
m_layout->addWidget(m_image_viewer);
QObject::connect(&m_capture, &Capture::matReady, &m_converter, &Converter::processFrame);
QObject::connect(&m_converter, &Converter::imageReady, m_image_viewer, &ImageViewer::setImage);
connect(m_camera_list, SIGNAL(currentIndexChanged(int)), this, SLOT(selectedCameraChanged(int)));
connect(m_effects_list, SIGNAL(currentIndexChanged(int)), this, SLOT(effectsChanged(int)));
connect(m_capture_btn, SIGNAL(clicked()), this, SLOT(captureAndSave()));
}
......@@ -195,6 +200,15 @@ void CameraDisplay::selectedCameraChanged(int camera_index) {
QMetaObject::invokeMethod(&m_capture, "start", Q_ARG(int, camera_index));
}
void CameraDisplay::effectsChanged(int effect) {
switch(effect) {
case 0:
break;
case 1:
break;
}
}
void CameraDisplay::captureAndSave() {
}
......@@ -108,6 +108,8 @@ protected:
protected Q_SLOTS:
void selectedCameraChanged(int camera_index);
void effectsChanged(int effect);
void captureAndSave();
private:
......@@ -115,15 +117,17 @@ private:
QVBoxLayout *m_layout;
QComboBox *m_camera_list;
QComboBox *m_effects_list;
QPushButton *m_capture_btn;
ImageViewer *m_image_viewer;
int m_camera;
Capture m_capture;
Converter m_converter;
IThread m_capture_thread;
IThread m_converter_thread;
};
};
#endif //MINOTAUR_CPP_CAMERA_H
#include "squares.h"
#include <opencv2/videoio.hpp>
#include <opencv2/opencv.hpp>
int thresh = 0;
int N = 50;
using std::vector;
using namespace cv;
static double angle(Point pt1, Point pt2, Point pt0) {
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1 * dx2 + dy1 * dy2) / sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2) + 1e-10);
}
// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
static void findSquares(const cv::Mat &image, vector<vector<Point> > &squares) {
squares.clear();
Mat pyr, timg, gray0(image.size(), CV_8U), gray;
// down-scale and upscale the image to filter out the noise
pyrDown(image, pyr, Size(image.cols / 2, image.rows / 2));
pyrUp(pyr, timg, image.size());
vector<vector<Point> > contours;
// find squares in every color plane of the image
for (int c = 0; c < 3; c++) {
int ch[] = {c, 0};
mixChannels(&timg, 1, &gray0, 1, ch, 1);
// try several threshold levels
for (int l = 0; l < N; l++) {
// hack: use Canny instead of zero threshold level.
// Canny helps to catch squares with gradient shading
if (l == 0) {
// apply Canny. Take the upper threshold from slider
// and set the lower to 0 (which forces edges merging)
Canny(gray0, gray, 0, thresh, 5);
// dilate canny output to remove potential
// holes between edge segments
dilate(gray, gray, Mat(), Point(-1, -1));
} else {
// apply threshold if l!=0:
// tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
gray = gray0 >= (l + 1) * 255 / N;
}
// find contours and store them all as a list
findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
vector<Point> approx;
// test each contour
for (size_t i = 0; i < contours.size(); i++) {
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true) * 0.02, true);
// square contours should have 4 vertices after approximation
// relatively large area (to filter out noisy contours)
// and be convex.
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if (approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 1000 &&
isContourConvex(Mat(approx))) {
double maxCosine = 0;
for (int j = 2; j < 5; j++) {
// find the maximum cosine of the angle between joint edges
double cosine = fabs(angle(approx[j % 4], approx[j - 2], approx[j - 1]));
maxCosine = MAX(maxCosine, cosine);
}
// if cosines of all angles are small
// (all angles are ~90 degree) then write quandrange
// vertices to resultant sequence
if (maxCosine < 0.3)
squares.push_back(approx);
}
}
}
}
}
// the function draws all the squares in the image
static void drawSquares(cv::Mat &image, const vector<vector<Point> > &squares) {
for (size_t i = 0; i < squares.size(); i++) {
const Point *p = &squares[i][0];
int n = (int) squares[i].size();
polylines(image, &p, &n, 1, true, Scalar(0, 255, 0), 3, LINE_AA);
}
}
void Squares::modify(cv::Mat *img) {
vector<vector<Point> > * squares = new vector<vector<Point> >;
const cv::Mat * new_img = img;
findSquares(*new_img, *squares);
drawSquares(*img, *squares);
}
\ No newline at end of file
#ifndef MINOTAUR_SQUARES_H
#define MINOTAUR_SQUARES_H
#include "modify.h"
class Squares : public VideoModifier {
public:
void modify(cv::Mat *img) override;
private:
};
#endif
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment