Lecture
lecture-2-image-features-optimized
Lab
You’ll need this zip file for the second part of the lab: [pkmImageFeatureDetector.zip]
cv2
Detecting and Drawing Image Features
testApp.h
#pragma once
#include "ofMain.h"
#include "ofxCvMain.h"
using namespace cv;
class testApp : public ofBaseApp{
public:
// redeclaration of functions (declared in base class)
void setup();
void setupFeatures();
void update();
void draw();
void keyPressed(int key);
int width, height;
float scalar;
ofVideoGrabber camera;
ofxCvColorImage cv_color_img;
ofxCvGrayscaleImage cv_luminance_img;
Mat mat_image;
unsigned int current_detector;
vector<string> feature_detectors;
cv::Ptr<FeatureDetector> feature_detector;
vector<KeyPoint> keypoints;
};
testApp.cpp
#include "testApp.h"
// here we "define" the methods we "declared" in the "testApp.h" file
// i get called once
void testApp::setup(){
scalar = 1.0f;
width = 640;
height = 480;
camera.initGrabber(width, height);
cv_color_img.allocate(width, height);
cv_luminance_img.allocate(width, height);
feature_detectors.push_back("SURF");
feature_detectors.push_back("DynamicSURF");
feature_detectors.push_back("PyramidSURF");
feature_detectors.push_back("GridSURF");
feature_detectors.push_back("SIFT");
feature_detectors.push_back("STAR");
feature_detectors.push_back("DynamicSTAR");
feature_detectors.push_back("PyramidSTAR");
feature_detectors.push_back("GridSTAR");
feature_detectors.push_back("FAST");
feature_detectors.push_back("DynamicFAST");
feature_detectors.push_back("PyramidFAST");
feature_detectors.push_back("GridFAST");
feature_detectors.push_back("GFTT");
feature_detectors.push_back("PyramidGFTT");
feature_detectors.push_back("MSER");
feature_detectors.push_back("PyramidMSER");
feature_detectors.push_back("HARRIS");
feature_detectors.push_back("PyramidHARRIS");
current_detector = 0;
feature_detector = FeatureDetector::create(feature_detectors[current_detector]);
ofSetFrameRate(60.0f);
ofSetWindowShape(width * scalar, height * scalar);
}
// i get called in a loop that runs until the program ends
void testApp::update(){
camera.update();
if (camera.isFrameNew()) {
cv_color_img.setFromPixels(camera.getPixelsRef());
cv_color_img.convertRgbToHsv();
cv_color_img.convertToGrayscalePlanarImage(cv_luminance_img, 2);
mat_image = Mat(cv_luminance_img.getCvImage());
keypoints.clear();
feature_detector->detect(mat_image, keypoints);
}
}
// i also get called in a loop that runs until the program ends
void testApp::draw(){
ofBackground(0);
ofPushMatrix();
ofScale(scalar, scalar);
ofSetColor(255, 255, 255);
camera.draw(0, 0);
ofNoFill();
ofSetColor(200, 100, 100);
vector<KeyPoint>::iterator it = keypoints.begin();
while(it != keypoints.end())
{
ofPushMatrix();
float radius = it->size/2;
ofTranslate(it->pt.x - radius, it->pt.y - radius, 0);
ofRotate(it->angle, 0, 0, 1);
ofRect(0, 0, radius, radius);
ofPopMatrix();
it++;
}
ofPopMatrix();
ofSetColor(255, 255, 255);
string draw_string = ofToString(current_detector+1) + string("/") +
ofToString(feature_detectors.size()) + string(": ") +
feature_detectors[current_detector];
ofDrawBitmapString(draw_string, 20, 20);
draw_string = string("# of features: ") + ofToString(keypoints.size());
ofDrawBitmapString(draw_string, 20, 35);
draw_string = string("fps: ") + ofToString(ofGetFrameRate());
ofDrawBitmapString(draw_string, 20, 50);
}
void testApp::keyPressed(int key){
if(key == 'n')
{
current_detector = (current_detector + 1) % feature_detectors.size();
feature_detector = FeatureDetector::create(feature_detectors[current_detector]);
}
}
Detecting Planar Objects
testApp.h
/*
* Created by Parag K. Mital - http://pkmital.com
* Contact: parag@pkmital.com
*
* Copyright 2011 Parag K. Mital. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _TEST_APP
#define _TEST_APP
#include "ofMain.h"
#include "pkmImageFeatureDetector.h"
#include "ofxOpenCv.h"
const int CAM_WIDTH = 320;
const int CAM_HEIGHT = 240;
const int SCREEN_WIDTH = CAM_WIDTH*2;
const int SCREEN_HEIGHT = CAM_HEIGHT + 75;
class testApp : public ofBaseApp {
public:
~testApp();
void setup();
void update();
void draw();
void drawKeypoints(vector<KeyPoint> keypts);
void keyPressed (int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);
ofVideoGrabber camera;
ofxCvColorImage color_img, color_roi_img;
ofxCvGrayscaleImage gray_search_img,
gray_template_img;
float x_start,
x_end,
y_start,
y_end;
cv::Point2f low_pass_bounding_box[4],
prev_pass_bounding_box[4];
float alpha;
bool choosing_img,
chosen_img;
pkmImageFeatureDetector detector;
vector<cv::KeyPoint> img_template_keypoints,
img_search_keypoints;
};
#endif
testApp.cpp
/*
* Created by Parag K. Mital - http://pkmital.com
* Contact: parag@pkmital.com
*
* Copyright 2011 Parag K. Mital. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "testApp.h"
//--------------------------------------------------------------
testApp::~testApp(){
}
void testApp::setup(){
// init video input
camera.initGrabber(CAM_WIDTH,CAM_HEIGHT);
camera.setUseTexture(true);
// window setup
ofSetWindowShape(SCREEN_WIDTH, SCREEN_HEIGHT);
ofSetVerticalSync(true);
ofSetFrameRate(60);
ofBackground(0,0,0);
// allocate stuff
color_img.allocate(CAM_WIDTH, CAM_HEIGHT);
gray_search_img.allocate(CAM_WIDTH, CAM_HEIGHT);
alpha = 0.6;
choosing_img = false;
chosen_img = false;
}
//--------------------------------------------------------------
void testApp::update(){
camera.update();
if(camera.isFrameNew())
{
// get camera img into iplimage
color_img.setFromPixels(camera.getPixels(), CAM_WIDTH, CAM_HEIGHT);
color_img.convertRgbToHsv();
if (chosen_img) {
color_img.convertToGrayscalePlanarImage(gray_search_img, 2);
detector.setImageSearch(gray_search_img.getCvImage());
detector.update();
img_search_keypoints = detector.getImageSearchKeypoints();
ofCircle(detector.dst_corners[0].x, detector.dst_corners[0].y, 10);
low_pass_bounding_box[0] = detector.dst_corners[0] * (1-alpha) + prev_pass_bounding_box[0] * alpha;
low_pass_bounding_box[1] = detector.dst_corners[1] * (1-alpha) + prev_pass_bounding_box[1] * alpha;
low_pass_bounding_box[2] = detector.dst_corners[2] * (1-alpha) + prev_pass_bounding_box[2] * alpha;
low_pass_bounding_box[3] = detector.dst_corners[3] * (1-alpha) + prev_pass_bounding_box[3] * alpha;
prev_pass_bounding_box[0] = low_pass_bounding_box[0];
prev_pass_bounding_box[1] = low_pass_bounding_box[1];
prev_pass_bounding_box[2] = low_pass_bounding_box[2];
prev_pass_bounding_box[3] = low_pass_bounding_box[3];
}
}
}
//--------------------------------------------------------------
void testApp::draw(){
ofBackground(0,0,0);
ofSetColor(255, 255, 255);
// camera image
camera.draw(0, 0);
if (chosen_img) {
ofSetColor(200, 100, 100);
drawKeypoints(img_search_keypoints);
ofPushMatrix();
ofTranslate(CAM_WIDTH, 0, 0);
ofSetColor(255, 255, 255);
gray_template_img.draw(0, 0);
ofSetColor(200, 100, 100);
drawKeypoints(img_template_keypoints);
ofPopMatrix();
ofSetColor(200, 200, 200);
ofLine(low_pass_bounding_box[0].x, low_pass_bounding_box[0].y,
low_pass_bounding_box[1].x, low_pass_bounding_box[1].y);
ofLine(low_pass_bounding_box[2].x, low_pass_bounding_box[2].y,
low_pass_bounding_box[1].x, low_pass_bounding_box[1].y);
ofLine(low_pass_bounding_box[2].x, low_pass_bounding_box[2].y,
low_pass_bounding_box[3].x, low_pass_bounding_box[3].y);
ofLine(low_pass_bounding_box[0].x, low_pass_bounding_box[0].y,
low_pass_bounding_box[3].x, low_pass_bounding_box[3].y);
}
// draw a rectanlge around the current selection
if (choosing_img) {
int x = mouseX;
int y = mouseY;
ofNoFill();
ofRect(x_start < x ? x_start : x,
y_start < y ? y_start : y,
abs(x_start - x),
abs(y_start - y));
}
}
void testApp::drawKeypoints(vector<KeyPoint> keypts)
{
vector<KeyPoint>::iterator it = keypts.begin();
while(it != keypts.end())
{
ofPushMatrix();
float radius = it->size/2;
ofTranslate(it->pt.x - radius, it->pt.y - radius, 0);
ofRotate(it->angle, 0, 0, 1);
ofRect(0, 0, radius, radius);
ofPopMatrix();
it++;
}
}
//--------------------------------------------------------------
void testApp::keyPressed (int key){
switch (key){
case 's':
camera.videoSettings();
break;
case 'n':
{
detector.changeDetector();
if(chosen_img)
img_template_keypoints = detector.getImageTemplateKeypoints();
break;
}
case '1':
break;
case '2':
break;
case 'b':
break;
}
}
//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){
}
//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
// start a rectangle selection
if(!choosing_img)
{
choosing_img = true;
x_start = x;
y_start = y;
}
}
//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
// end the rectangle selection
if (choosing_img) {
choosing_img = false;
x_end = x;
y_end = y;
if(x_start > x_end)
std::swap(x_start, x_end);
if(y_start > y_end)
std::swap(y_start, y_end);
int w = x_end - x_start;
int h = y_end - y_start;
cvSetImageROI(color_img.getCvImage(),
cvRect(x_start,
y_start,
w, h));
if (color_roi_img.bAllocated) {
gray_template_img.clear();
color_roi_img.clear();
}
gray_template_img.allocate(w, h);
color_roi_img.allocate(w, h);
color_roi_img = color_img;
color_roi_img.convertToGrayscalePlanarImage(gray_template_img, 2);
cvResetImageROI(color_img.getCvImage());
detector.setImageTemplate(gray_template_img.getCvImage());
img_template_keypoints = detector.getImageTemplateKeypoints();
chosen_img = true;
}
}
//--------------------------------------------------------------
void testApp::windowResized(int w, int h){
}