Image access problem across different .cpp files

Hi I have been through a number of the topics on how to organise OF in terms of a shared image resource
I am still unclear about it and could do with some assistance
I want to use a live video grab, divide it into 12 sections and control the behaviour of each section using a class
This means that each instance of the class would be dealing with a separate part of the webcam image
I am unclear about how to give each instance access to the webcam information
I have tried the thread approach already without success and I have also used the Singleton example and got this to work with integers so that these are printed out in the Activity monitor
Coming from a Processing background , this is a very different set up

What do you mean exactly? Do you want to modify the image? Or just read it?

You could work with ofPixels and just read and write each section through the pixel reference pointer, it might even be possible to create ofPixels to reference subregions, using ofPixels::setFromExternalPixels.

Hi Chuckleplant
I did a piece in Processing where I was able to vibrate and resize sections of a webcam feed


I suppose I don’t yet understand the ofPixels::setFromExternalPixels at least I haven’t used it yet
In Processing each instance of my class had just a part of the image to look after and I was able to run through all the objects and keep an eye on what they were doing

I really don’t have any experience on Processing, but that looks like something you’d want to do using shaders. How did you do it with processing?

Hi again
I created a class as in the usual ofBall example but I associated a part of the video image to each instance. Each instance’s X and Y position could then be modified dynamically. Also its size.
I have already been through instance creation in oF and I am happy with that. I’m just a bit stuck on how each instance can see the same video grabber source. Any help would be very much appreciated

Here’s the code I have for my ofBall.cpp

//
// ofBall.cpp
// mySketchBall2
//
// Created by richard colson on 16/10/2014.
//
//

#include “ofBall.h”
#include “ofApp.h”

ofBall::ofBall(float _x, float _y, int _dim)
{

x = ofRandom(0, ofGetWidth());      // give some random positioning
y = ofRandom(0, ofGetHeight());

speedX = ofRandom(-1, 20);           // and random speed and direction
speedY = ofRandom(-1, 20);

dim = 20;

}

void ofBall::update(){

if(x < 0 ){
    x = 0;
    speedX *= -1;
} else if(x > ofGetWidth()){
    x = ofGetWidth();
    speedX *= -1;
}

if(y < 0 ){
    y = 0;
    speedY *= -1;
} else if(y > ofGetHeight()){
    y = ofGetHeight();
    speedY *= -1;
}

x+=speedX;
y+=speedY;

ofPixels pxs;
fbo2.readToPixels(pxs);
colorImage.setFromPixels(pxs);

}

void ofBall::draw(){
colorImage.draw(0,0);
cout << “test” << test << endl;

}

Hi,
You could have a fullFrame class, that updates an image from the camera, and then updates each subFrame instance with a portion of the image.

  • on each frame
  • fullFrame <- update from camera
  • for each subFrame s
    • s <- update from fullFrame
    • modify s

Then each subframe would have a copy of a portion from the same grabbed frame.

Thanks chuckleplant
I will try this
I was also directed to this thread


by Jim Alliban but there are still things I need to learn about how C++ deals with memory

Hi chuckleplant
I looked at an example somewhere where the ball class was a part of the ofApp.h rather than being separate. This gets round the problem of access to the webcam information

Here’s what I used:

ofapp.h

#pragma once
#ifndef _TEST_APP
#define _TEST_APP

#include "ofMain.h"

struct Ball {
    int x;
    int y;
    int vx;
    int vy;
    int radius;
    int red,green,blue;
};
class ofApp : public ofBaseApp{
	public:
		void setup();
		void update();
		void draw();
		
		void keyPressed(int key);
		void keyReleased(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);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
    
        Ball balls[100];
        ofImage img,image;
        ofVideoGrabber 		vidGrabber;
        unsigned char * 	videoInverted;
        ofTexture			videoTexture;
        int 				camWidth;
        int 				camHeight;
        ofFbo               fbo;
};

#endif
#include "ofApp.h"

//--------------------------------------------------------------

//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(255,255,0);
    ofSetFrameRate(30);
    
    img.loadImage("funnyman.png");
    img.setAnchorPercent(.5, .5);
    
    for (int i=0; i<10; i++) {
        balls[i].x = ofRandomWidth();
        balls[i].y = ofRandomHeight();
        balls[i].vx = ofRandom(-10,10);
        balls[i].vy = ofRandom(-10,10);
        balls[i].radius = ofRandom(50,80);
        balls[i].red = ofRandom(0,255);
        balls[i].green = ofRandom(0,255);
        balls[i].blue = ofRandom(0,255);
    }
    camWidth 		= 1280;	// try to grab at this size.
    camHeight 		= 720;
    
    //we can now get back a list of devices.
    vector<ofVideoDevice> devices = vidGrabber.listDevices();
    
    for(int i = 0; i < devices.size(); i++){
        cout << devices[i].id << ": " << devices[i].deviceName;
        if( devices[i].bAvailable ){
            cout << endl;
        }else{
            cout << " - unavailable " << endl;
        }
    }
    
    vidGrabber.setDeviceID(0);
    vidGrabber.setDesiredFrameRate(60);
    vidGrabber.initGrabber(camWidth,camHeight);
    
    videoInverted 	= new unsigned char[camWidth*camHeight*3];
    videoTexture.allocate(camWidth,camHeight, GL_RGB);
    ofSetVerticalSync(true);

    
}

ofApp.cpp

//--------------------------------------------------------------
void ofApp::update() {
    
    vidGrabber.update();
    
    if (vidGrabber.isFrameNew()){
        int totalPixels = camWidth*camHeight*3;
        unsigned char * pixels = vidGrabber.getPixels();
        //for (int i = 0; i < totalPixels; i++){
         //   videoInverted[i] = 255 - pixels[i];
      //  }
       // videoTexture.loadData(videoInverted, camWidth,camHeight, GL_RGB);
        
        
        //image.drawSubsection(mouseX, mouseY, 100, 100, mouseX, mouseY);
    }
    
    for (int i=0; i<10; i++) {
        
        balls[i].x = balls[i].x + balls[i].vx;
        balls[i].y = balls[i].y + balls[i].vy;
        
        if (balls[i].x<0 || balls[i].x > ofGetWidth()) {
            balls[i].vx = -balls[i].vx;
        }
        
        if (balls[i].y<0 || balls[i].y > ofGetHeight()) {
            balls[i].vy = -balls[i].vy;
        }
        
        //if (ofDist(ballA.x, ballA.y, ballB.x, ballB.y) < 50
        
        for (int j=0; j<10; j++) {
            
            if (i==j) continue;
            
            float distance = ofDist(balls[i].x, balls[i].y, balls[j].x, balls[j].y);
            
            if (distance < balls[i].radius+balls[j].radius) {
                balls[i].vx = -balls[i].vx;
                balls[i].vy = -balls[i].vy;
                
                balls[j].vx = -balls[j].vx;
                balls[j].vy = -balls[j].vy;
            }
        }
        
    }
    
    
}

//--------------------------------------------------------------
void ofApp::draw(){
    
    ofSetColor(255, 255, 255);
    
    
    for (int i=0; i<10; i++) {
        ofSetColor(balls[i].red, balls[i].green, balls[i].blue);
        //ofCircle(balls[i].x, balls[i].y, balls[i].radius);
        image.setFromPixels( vidGrabber.getPixelsRef() );
       // fbo.allocate(1280,720);
        //fbo.readToPixels(image);
        
        
       // fbo.begin();
        //ofClear(255,255,255, 0);
        //image.draw(0, 0);
        
        //fbo.end();
        image.drawSubsection(balls[i].x, balls[i].y, balls[i].radius*2, balls[i].radius*2,balls[i].radius*2, balls[i].radius*2);


       // image.draw(balls[i].x, balls[i].y, balls[i].radius*2, balls[i].radius*2);
    }
    //vidGrabber.draw(20,20);
    //videoTexture.draw(20+camWidth,20+camHeight,camWidth,camHeight);
}

Okay, I see. So your main problem was accessing a superior’s class data. You might want to take a look at dependency injection as a concept.

For instance

class SuperiorClass
{
public:
    void init()
    {
        // Initialize balls
        balls[i].setImageReference( videoFrame );
    }

    void update()
    {
        updateFrame( videoFrame );
        for(...)
        {
            balls[i].doStuffWithImage( );
        }
    }
private:
    ofImage videoFrame;
    vector<InferiorClass> balls;
}

class InferiorClass
{
public:
    void setImageReference(ofImage * image);
    void doStuffWithImage();
private:
    ofImage * pointerToFrame;
}

Notice how you only need to set the reference to the inferior class once, then you just need to update your videoFrame instance, and the inferior classes will be accessing the updated image.

Careful with pointers though! In the previous sample, the InferiorClass instances can access, modify and delete the videoFrame, which might not be desireable.