Spent the day figuring out how to use openCv functions with openFrameworks, and thought I’d share the results with the world.
Not sure this is the best place, but I would have liked this to be here this morning
The example used loads a mask map(?) from a png file and allows you to select which are of the image you want to crop out based on the colour of the mask.
The goal is to have a contour finder run on only sections of an image.
The xcode project : http://bit.ly/theronOf4712
Tried to give sound advice, but if im wrong, let me know
//Integers to set the height and width of our workspace
int width, height;
//The grabber that gets frames from the webcam
ofVideoGrabber vidGrabber;
//An ofImage so that we can load in an image file
//Im not sure if this can be done directly with cvImages, if so, let me know
ofImage ofMask;
//Some openCv images
ofxCvColorImage cvImage, cvMask, cvBlank, cvDest;
ofxCvGrayscaleImage cvGrayMask;
//And some pointers to IplImages (openCv's native image format)
//These cant be on the same line for some reason???
IplImage * iplImg;
IplImage * iplMask;
IplImage * iplGrayMask;
IplImage * iplDest;
/*
Theron Burger 2011
pftburger@gmail.com
theronBurger.com
Some notes on dealing with openCv functions
some functions give a destination.
If the program crashes (with "Program received signal: SIGABRT ")
and says "Previous frame inner to this frame (gdb could not unwind past this frame)"
check if the destination needs to be a single channel image (grayscale)
some functions require a cvScalar type
this can be created with the cvScalar() or cvScalarAll() functions
cvScalar takes 4 doubles (doubles are "double accuracy" floats) IE Red, Blue, Green and Alpha
cvScalarAll takes one double, and sets all four to the same thing.
iplImages are the image format openCv uses.
IPL stands for Image Processing Library
they can be one channel (grayscale), three channel (RGB), or four channel (RGB+Alpha)
oh, and generally, if you get a EXC_BAD_ACCESS error
it means that you tried to access something where nothing exists.
try allocating all your images before hand, check that the png file exists, and if you have any loops
make sure you counter stays within the range of the object.
*/
#include "testApp.h"
//--------------------------------------------------------------
void testApp::setup() {
//Set up the scene, the mask map must be the same size!
width = 400;
height = 300;
//pre allocate all the images. This helps by giving the empty containers a size
//so that if we query them, we dont get out of range
cvImage.allocate(width,height);
cvMask.allocate(width,height);
cvGrayMask.allocate(width,height);
cvBlank.allocate(width,height);
cvDest.allocate(width,height);
//Start the video grabber, this gets an image stream from the webcam
vidGrabber.initGrabber(width, height);
//Load up the mask image
//This image needs to be pre-made in photoshop using the pencil tool, in dissolve mode
//This is important, as the brush tool tries to blend the edges, causing blurred edges
//When we run the cvInRangeS function on a blurred edge, we get little dots on the mask
//These little dots cause islands in the final image, and create false blobs because of their size
//Load the image into a ofImage
ofMask.loadImage("mask.png");
//copy it to a cvColorImage
cvMask.setFromPixels(ofMask.getPixels(), width, height);
//then copy it to a cvGrascaleImage
cvGrayMask = cvMask;
//Assign pointers to the iplImages hidden inside the
iplMask = cvMask.getCvImage();
iplGrayMask = cvGrayMask.getCvImage();
iplDest = cvDest.getCvImage();
iplImg = cvImage.getCvImage();
//Now that we have the mask map, we need to extract only the section we are interested in
//To do that, we select a colour, and copy only the parts of the image that match
//Set the colour "key" we are looking for in the mask map
double key = 204;
//The destination iplImage must be single channel :)
cvInRangeS(iplMask, cvScalarAll(key-1), cvScalarAll(key+1), iplGrayMask);
//We should flag the cvImage as change, but it seems to work without it.
//cvGrayMask.flagImageChanged();
}
//--------------------------------------------------------------
void testApp::update() {
//Update the vidGrabber
vidGrabber.update();
//Check if the webcam has captured a new frame
if (vidGrabber.isFrameNew()) {
//get the new frame from the vidGrabber and copy it to the cvImage
cvImage.setFromPixels(vidGrabber.getPixels(), width, height);
//Here we copy the image from iplImg to iplDest, only where iplGrayMask is nonZero ie, not black
//Once again, mask must be a single channel image
cvCopy(iplImg, iplDest, iplGrayMask);
//Tell cvDest that we have updated its cvImage, so that it can do its magic
//If we dont do this, we wont see anything when we draw the image
//This time it seems to be necessary :P
cvDest.flagImageChanged();
}
}
//--------------------------------------------------------------
void testApp::draw() {
//Draw a mid gray background
ofBackground(127.5f);
//Make sure the "pen" colour is white, if its not, the images will be shaded the current pen colour
ofSetColor(255);
//draw all the images to the screen
cvImage.draw(10,10);
cvDest.draw(420,10);
cvMask.draw(10,320);
cvGrayMask.draw(420,320);
}
some keywords for search
convert IplImage to cvImage
convert IplImage to ofxCvColorImage
convert IplImage to ofxCvGrayscaleImage
convert IplImage to openCv Image
Draw IplImage
use openCv functions
image mask
mask from jpg
mask from png
cvScalar()
cvInRange
cvCopy