Using videoGrabber with ofMesh in OpenFrameworks on iOS - ios

First time diving into OF on iOS...exciting! As a first run I'm trying to port an app I made before into an iOS app. Its a pretty simple rutt etra-like effect on video coming in from the video camera. I have it working as a mac app, but I can't seem to get it displaying properly on my iPhone. The mesh is drawing, but I don't think I'm getting pixel values from my camera to vidPixels in order to change the color of my mesh. I'm basing this off of the videoGrabberExample in OF iOS 0072. I'm on a MacBook Pro, 10.7.5, running Xcode 4.5.2.
Can anyone give this a look and let me know if I'm doing something wrong? :) Thanks so much in advance.
Code:
testApp.mm
#include "testApp.h"
#include "ofGLUtils.h"
#include "ofGLRenderer.h"
//--------------------------------------------------------------
void testApp::setup(){
ofxiPhoneSetOrientation(OFXIPHONE_ORIENTATION_LANDSCAPE_RIGHT);
ofSetFrameRate(30);
grabber.initGrabber(480, 360);
yStep = 5;
xStep = 5;
// drawRuttEtra = false;
ofBackground(0, 0, 0);
}
//--------------------------------------------------------------
void testApp::update(){
//ofBackground(255,255,255);
grabber.update();
if(grabber.isFrameNew()){
vidPixels = grabber.getPixelsRef();
}
}
//--------------------------------------------------------------
void testApp::draw(){
glEnable(GL_DEPTH_TEST);
ofMesh mesh;
int rowCount = 0;
for (int y = 0; y<grabber.height; y+=yStep){
ofNoFill();
mesh.setMode(OF_PRIMITIVE_LINE_STRIP);
if (rowCount % 2 == 0) {
for (int x = 0; x < grabber.width; x += xStep){
ofColor curColor = vidPixels.getColor(x, y);
mesh.addColor(ofColor(curColor));
mesh.addVertex(ofVec3f(x,y, curColor.getBrightness() * 0.3));
}
} else {
for (int x = grabber.width-1; x >= 0; x -= xStep){
ofColor curColor = vidPixels.getColor(x, y);
mesh.addColor(ofColor(curColor));
mesh.addVertex(ofVec3f(x,y, curColor.getBrightness() * 0.3)); }
}
rowCount++;
}
mesh.draw();
// grabber.draw(0,0);
}
testApp.h
#pragma once
#include "ofMain.h"
#include "ofxiPhone.h"
#include "ofxiPhoneExtras.h"
class testApp : public ofxiPhoneApp{
public:
void setup();
void update();
void draw();
void exit();
void touchDown(ofTouchEventArgs & touch);
void touchMoved(ofTouchEventArgs & touch);
void touchUp(ofTouchEventArgs & touch);
void touchDoubleTap(ofTouchEventArgs & touch);
void touchCancelled(ofTouchEventArgs & touch);
void lostFocus();
void gotFocus();
void gotMemoryWarning();
void deviceOrientationChanged(int newOrientation);
ofVideoGrabber grabber;
ofTexture tex;
unsigned char * pix;
//rutt etra effect
int yStep;
int xStep;
bool drawRuttEtra;
ofPixels vidPixels;
};
main.mm
#include "ofMain.h"
#include "testApp.h"
int main(){
ofSetupOpenGL(1024,768, OF_FULLSCREEN); // <-------- setup the GL context
ofRunApp(new testApp);
}
I tried doing some debugging to see what might be happening.
I wanted to make sure ifFrameNew() works. Trying:
if(grabber.isFrameNew()){
cout<< "i'm grabbing new pixels!" << endl;
vidPixels = grabber.getPixelsRef();
}
prints "i'm grabbing new pixels!", so that if block is working.
In my double for loop, if I cout the value of vidPixels.getColor(x,y)
cout<<vidPixels.getColor(x,y) << endl;
I get all 255...which makes me think grabber.getPixelsRef() isn't working how I thought it should.
Any ideas?

Related

Creating Terrain Map with SRTM HGT File

I am working on an iOS application. Where I show the Elevation and Topography map of a certain area. I have managed to download the .hgt file within app from here.
So far I am able to extract the Elevation from the hgt file. Now I have to also show the Terrain Map for that area. I have been searching about it and I think I can't create terrain map directly with hgt file within iOS application. I have to use GRASS GIS, SRTM2OSM or TileMill to create terrain map and then use it in application.
Can please anyone direct me what I can do here and how to proceed.
EDIT:
I have asked to not to use any kind of map for this. So basically I have to create the map by using core drawing, and I have no idea about it.
Something Like this without the text:
With iOS you have access to Maps through MapKit framework to display map or satellite imagery directly from your app's interface, you can use also Google Maps through Google Maps SDK for iOS but both (iOS Maps and Google Maps) don't have a terrain level.
So to avoid to re-create something that already exist you can take a look to the OpenStreetMaps frameworks, here you can find many available frameworks, one of them is called MapBox and you can download the latest sources and example here
As you can read from wiki pages we have also the terrain level:
I think it's a really useful library, updated and working with swift 4 , here you can find an easy tutorial to start:
import Mapbox
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let mapView = MGLMapView(frame: view.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.setCenter(CLLocationCoordinate2D(latitude: 40.74699, longitude: -73.98742), zoomLevel: 9, animated: false)
view.addSubview(mapView)
// to show the terrain level
mapView.styleURL = MGLStyle.outdoorsStyleURL()
}
}
I have to create the map by using core drawing
You can draw an Map object from SRTM HGT file [1]
For reading interpolated height from SRTM HGT files [2]
Below is code working with .cpp file you can get some idea for how to draw it from SRTM [3]
#include "generator/srtm_parser.hpp"
#include "coding/endianness.hpp"
#include "coding/zip_reader.hpp"
#include "base/logging.hpp"
#include <iomanip>
#include <sstream>
namespace generator
{
namespace
{
size_t constexpr kArcSecondsInDegree = 60 * 60;
size_t constexpr kSrtmTileSize = (kArcSecondsInDegree + 1) * (kArcSecondsInDegree + 1) * 2;
struct UnzipMemDelegate : public ZipFileReader::Delegate
{
UnzipMemDelegate(std::string & buffer) : m_buffer(buffer), m_completed(false) {}
// ZipFileReader::Delegate overrides:
void OnBlockUnzipped(size_t size, char const * data) override { m_buffer.append(data, size); }
void OnStarted() override
{
m_buffer.clear();
m_completed = false;
}
void OnCompleted() override { m_completed = true; }
std::string & m_buffer;
bool m_completed;
};
} // namespace
// SrtmTile ----------------------------------------------------------------------------------------
SrtmTile::SrtmTile()
{
Invalidate();
}
SrtmTile::SrtmTile(SrtmTile && rhs) : m_data(move(rhs.m_data)), m_valid(rhs.m_valid)
{
rhs.Invalidate();
}
void SrtmTile::Init(std::string const & dir, ms::LatLon const & coord)
{
Invalidate();
std::string const base = GetBase(coord);
std::string const cont = dir + base + ".SRTMGL1.hgt.zip";
std::string file = base + ".hgt";
UnzipMemDelegate delegate(m_data);
try
{
ZipFileReader::UnzipFile(cont, file, delegate);
}
catch (ZipFileReader::LocateZipException const & e)
{
// Sometimes packed file has different name. See N39E051 measure.
file = base + ".SRTMGL1.hgt";
ZipFileReader::UnzipFile(cont, file, delegate);
}
if (!delegate.m_completed)
{
LOG(LWARNING, ("Can't decompress SRTM file:", cont));
Invalidate();
return;
}
if (m_data.size() != kSrtmTileSize)
{
LOG(LWARNING, ("Bad decompressed SRTM file size:", cont, m_data.size()));
Invalidate();
return;
}
m_valid = true;
}
feature::TAltitude SrtmTile::GetHeight(ms::LatLon const & coord)
{
if (!IsValid())
return feature::kInvalidAltitude;
double ln = coord.lon - static_cast<int>(coord.lon);
if (ln < 0)
ln += 1;
double lt = coord.lat - static_cast<int>(coord.lat);
if (lt < 0)
lt += 1;
lt = 1 - lt; // from North to South
size_t const row = kArcSecondsInDegree * lt;
size_t const col = kArcSecondsInDegree * ln;
size_t const ix = row * (kArcSecondsInDegree + 1) + col;
if (ix >= Size())
return feature::kInvalidAltitude;
return ReverseByteOrder(Data()[ix]);
}
std::string SrtmTile::GetBase(ms::LatLon coord)
{
std::ostringstream ss;
if (coord.lat < 0)
{
ss << "S";
coord.lat *= -1;
coord.lat += 1;
}
else
{
ss << "N";
}
ss << std::setw(2) << std::setfill('0') << static_cast<int>(coord.lat);
if (coord.lon < 0)
{
ss << "W";
coord.lon *= -1;
coord.lon += 1;
}
else
{
ss << "E";
}
ss << std::setw(3) << static_cast<int>(coord.lon);
return ss.str();
}
void SrtmTile::Invalidate()
{
m_data.clear();
m_data.shrink_to_fit();
m_valid = false;
}
// SrtmTileManager ---------------------------------------------------------------------------------
SrtmTileManager::SrtmTileManager(std::string const & dir) : m_dir(dir) {}
feature::TAltitude SrtmTileManager::GetHeight(ms::LatLon const & coord)
{
std::string const base = SrtmTile::GetBase(coord);
auto it = m_tiles.find(base);
if (it == m_tiles.end())
{
SrtmTile tile;
try
{
tile.Init(m_dir, coord);
}
catch (RootException const & e)
{
LOG(LINFO, ("Can't init SRTM tile:", base, "reason:", e.Msg()));
}
// It's OK to store even invalid tiles and return invalid height
// for them later.
it = m_tiles.emplace(base, std::move(tile)).first;
}
return it->second.GetHeight(coord);
}
} // namespace generator

How to reset / restart a Urho3D application scene to its initial state?

I want to reset my scene to its original state when the user presses a key, to facilitate testing or allow users to restart the game.
More precisely, how to organize my code, and what do I have to put into:
void HandleKeyDown(StringHash /*eventType*/, VariantMap& eventData) {
using namespace KeyDown;
int key = eventData[P_KEY].GetInt();
if (key == KEY_R) {
// TODO
}
}
to restart the application?
Here is a full runnable example, where I try to create a pong-like game:
#include <iostream>
#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Core/Object.h>
#include <Urho3D/Engine/Application.h>
#include <Urho3D/Engine/Engine.h>
#include <Urho3D/Engine/EngineDefs.h>
#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Graphics/DebugRenderer.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/Renderer.h>
#include <Urho3D/IO/File.h>
#include <Urho3D/IO/FileSystem.h>
#include <Urho3D/IO/MemoryBuffer.h>
#include <Urho3D/Input/Input.h>
#include <Urho3D/Input/InputEvents.h>
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Scene/Node.h>
#include <Urho3D/Scene/Scene.h>
#include <Urho3D/Scene/SceneEvents.h>
#include <Urho3D/UI/Font.h>
#include <Urho3D/UI/Text.h>
#include <Urho3D/UI/UI.h>
#include <Urho3D/Urho2D/CollisionBox2D.h>
#include <Urho3D/Urho2D/CollisionCircle2D.h>
#include <Urho3D/Urho2D/ConstraintPrismatic2D.h>
#include <Urho3D/Urho2D/PhysicsEvents2D.h>
#include <Urho3D/Urho2D/PhysicsWorld2D.h>
#include <Urho3D/Urho2D/RigidBody2D.h>
using namespace Urho3D;
class Main : public Application {
URHO3D_OBJECT(Main, Application);
public:
Main(Context* context) : Application(context) {}
virtual void Setup() override {
engineParameters_[EP_FULL_SCREEN] = false;
engineParameters_[EP_WINDOW_TITLE] = __FILE__;
engineParameters_[EP_WINDOW_HEIGHT] = 512;
engineParameters_[EP_WINDOW_WIDTH] = 512;
}
void Start() {
auto windowHeight = this->windowWidth;
auto wallLength = this->windowWidth;
auto wallWidth = this->windowWidth / 20.0f;
auto ballRadius = this->windowWidth / 20.0f;
auto ballRestitution = 1.0f;
auto playerLength = windowHeight / 4.0f;
this->score = 0;
this->steps = 0;
this->input = this->GetSubsystem<Input>();
// Events
SubscribeToEvent(E_KEYDOWN, URHO3D_HANDLER(Main, HandleKeyDown));
SubscribeToEvent(E_PHYSICSBEGINCONTACT2D, URHO3D_HANDLER(Main, HandlePhysicsBeginContact2D));
SubscribeToEvent(E_POSTRENDERUPDATE, URHO3D_HANDLER(Main, HandlePostRenderUpdate));
SubscribeToEvent(E_UPDATE, URHO3D_HANDLER(Main, HandleUpdate));
// Scene
this->scene = new Scene(this->context_);
this->scene->CreateComponent<Octree>();
this->scene->CreateComponent<DebugRenderer>();
this->scene->CreateComponent<PhysicsWorld2D>();
auto physicsWorld = scene->GetComponent<PhysicsWorld2D>();
physicsWorld->SetGravity(Vector2(0.0f, 0.0f));
this->physicsWorld = this->scene->GetComponent<PhysicsWorld2D>();
// Graphics
auto cameraNode = this->scene->CreateChild("Camera");
cameraNode->SetPosition(Vector3(windowWidth / 2.0f, windowHeight / 2.0f, -1.0f));
auto camera = cameraNode->CreateComponent<Camera>();
camera->SetOrthographic(true);
camera->SetOrthoSize(windowWidth);
auto renderer = GetSubsystem<Renderer>();
SharedPtr<Viewport> viewport(new Viewport(context_, this->scene, cameraNode->GetComponent<Camera>()));
renderer->SetViewport(0, viewport);
// Score
ResourceCache *cache = this->GetSubsystem<ResourceCache>();
auto ui = this->GetSubsystem<UI>();
this->text = ui->GetRoot()->CreateChild<Text>();
this->text->SetText(std::to_string(this->score).c_str());
this->text->SetFont(cache->GetResource<Font>("Fonts/Anonymous Pro.ttf"), 15);
this->text->SetHorizontalAlignment(HA_CENTER);
this->text->SetVerticalAlignment(VA_CENTER);
Node *wallNode;
RigidBody2D *wallBody;
{
wallNode = this->scene->CreateChild("BottomWall");
wallNode->SetPosition(Vector3(this->windowWidth / 2.0, wallWidth / 2.0f, 0.0f));
wallBody = wallNode->CreateComponent<RigidBody2D>();
auto box = wallNode->CreateComponent<CollisionBox2D>();
box->SetSize(Vector2(wallLength, wallWidth));
box->SetRestitution(0.0);
}
{
auto node = wallNode->Clone();
node->SetName("TopWall");
node->SetPosition(Vector3(this->windowWidth / 2.0f, windowHeight - (wallWidth / 2.0f), 0.0f));
}
{
auto& node = this->rightWallNode;
node = wallNode->Clone();
node->SetName("RightWall");
node->SetRotation(Quaternion(0.0f, 0.0f, 90.0f));
node->SetPosition(Vector3(this->windowWidth - (wallWidth / 2.0f), windowHeight / 2.0f, 0.0f));
}
{
auto& node = this->leftWallNode;
node = wallNode->Clone();
node->SetName("LeftWall");
node->SetRotation(Quaternion(0.0f, 0.0f, 90.0f));
node->SetPosition(Vector3(-wallWidth / 2.0f, windowHeight / 2.0f, 0.0f));
}
{
auto& node = this->playerNode;
node = wallNode->Clone();
node->SetName("Player");
node->SetRotation(Quaternion(0.0f, 0.0f, 90.0f));
node->SetPosition(Vector3(wallWidth / 2.0f, windowHeight / 2.0f, 0.0f));
auto body = node->GetComponent<RigidBody2D>();
body->SetBodyType(BT_DYNAMIC);
body->SetFixedRotation(true);
body->SetLinearDamping(4.0);
//auto constraint = node->CreateComponent<ConstraintPrismatic2D>();
//constraint->SetOtherBody(wallBody);
//constraint->SetAxis(Vector2(0.0f, 1.0f));
auto shape = node->GetComponent<CollisionBox2D>();
shape->SetDensity(this->playerDensity);
shape->SetFriction(1.0f);
shape->SetRestitution(0.0);
shape->SetSize(Vector2(playerLength, wallWidth));
}
{
this->ballNode = this->scene->CreateChild("Ball");
this->ballNode->SetPosition(Vector3(this->windowWidth / 4.0f, windowHeight / 2.0f, 0.0f));
auto body = this->ballNode->CreateComponent<RigidBody2D>();
body->SetBodyType(BT_DYNAMIC);
body->SetLinearVelocity(Vector2(2 * this->windowWidth, -windowHeight / 2.0f));
auto shape = this->ballNode->CreateComponent<CollisionCircle2D>();
shape->SetDensity(1.0f);
shape->SetFriction(1.0f);
shape->SetRadius(ballRadius);
shape->SetRestitution(ballRestitution);
}
}
void Stop() {}
private:
SharedPtr<Scene> scene;
Node *ballNode, *playerNode, *leftWallNode, *rightWallNode;
Text *text;
Input *input;
PhysicsWorld2D *physicsWorld;
uint64_t score, steps;
/// Larger means that the controls will react faster.
static constexpr float playerDensity = 10.0f;
static constexpr float windowWidth = 1.0f;
void HandleKeyDown(StringHash /*eventType*/, VariantMap& eventData) {
using namespace KeyDown;
int key = eventData[P_KEY].GetInt();
if (key == KEY_ESCAPE) {
engine_->Exit();
} else if (key == KEY_R) {
this->Start();
}
}
void HandlePhysicsBeginContact2D(StringHash eventType, VariantMap& eventData) {
using namespace PhysicsBeginContact2D;
auto nodea = static_cast<Node*>(eventData[P_NODEA].GetPtr());
auto nodeb = static_cast<Node*>(eventData[P_NODEB].GetPtr());
Node *otherNode;
bool isBall = false;
if (nodea == this->ballNode) {
otherNode = nodeb;
isBall = true;
}
if (nodeb == this->ballNode) {
otherNode = nodea;
isBall = true;
}
if (otherNode == this->rightWallNode) {
this->score++;
} else if (otherNode == this->leftWallNode) {
this->score = 0;
}
this->text->SetText(std::to_string(this->score).c_str());
File saveFile(this->context_, GetSubsystem<FileSystem>()->GetProgramDir() + String(this->steps) + ".xml", FILE_WRITE);
this->scene->SaveXML(saveFile);
}
void HandleUpdate(StringHash eventType, VariantMap& eventData) {
using namespace Update;
auto timeStep = eventData[P_TIMESTEP].GetFloat();
auto impuseMagnitude = this->windowWidth * this->playerDensity * timeStep * 10.0;
auto body = this->playerNode->GetComponent<RigidBody2D>();
if (this->input->GetKeyDown(KEY_DOWN)) {
body->ApplyForceToCenter(Vector2(0.0f, -impuseMagnitude), true);
} else if (this->input->GetKeyDown(KEY_UP)) {
body->ApplyForceToCenter(Vector2(0.0f, impuseMagnitude), true);
} else if (this->input->GetKeyDown(KEY_RIGHT)) {
body->ApplyForceToCenter(Vector2(impuseMagnitude, 0.0f), true);
} else if (input->GetKeyDown(KEY_LEFT)) {
body->ApplyForceToCenter(Vector2(-impuseMagnitude, 0.0f), true);
}
this->steps++;
}
void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData) {
this->physicsWorld->DrawDebugGeometry();
}
};
URHO3D_DEFINE_APPLICATION_MAIN(Main);
In my naive attempt, I've tried to simply call this->Start() from the callback, but it did not clear up everything: the UI still shows the old score, in addition to a new score superposed to it.
GitHub upstream: https://github.com/cirosantilli/Urho3D-cheat/blob/e58a643ccf855d659ee292aeb513e191e0c5bb95/pong.cpp
Also asked at: https://discourse.urho3d.io/t/how-to-reset-restart-a-urho3d-application-scene-to-its-initial-state/3831
To empty a Scene, call Scene::Clear() on it. This removes all the Scene's Components and child Nodes. After this you can call a function that rebuilds the scene.
Alternately you could create a custom reset event that all Objects that require some form of resetting subscribe their HandleReset methods to. To restart the game you would then call SendEvent(E_RESET).
Based on #Frode's answer, I've reorganized my code along:
void Start() override {
if (this->scene) {
this->scene->Clear();
} else {
this->scene = new Scene(this->context_);
// Setup text.
this->text = this->GetSubsystem<UI>()->GetRoot()->CreateChild<Text>();
// Other things that only need to be done once.
}
// Application state.
this->score = 0;
// Scene setup
{
this->scene->CreateComponent<Octree>();
this->scene->CreateChild("BottomWall");
}
}
and then:
void HandleKeyDown(StringHash /*eventType*/, VariantMap& eventData) {
using namespace KeyDown;
int key = eventData[P_KEY].GetInt();
if (key == KEY_R) {
this->Start();
}
}
I was kind of hoping that there would be a Clear() like method for the whole application (in particular, the UI does not get reset with Scene->Clear, but this solution is acceptable to me.
Updated working code at: https://github.com/cirosantilli/Urho3D-cheat/blob/cda28fea8028f4c7a5ebb7c4d7bace4a7d78d8e8/pong.cpp

How to detect collision events and run a callback in Urho3D in a 2D world?

I have managed to detect collisions in 3D, but the "analogous" 2D did not work.
For the 3D, I do:
SubscribeToEvent(E_NODECOLLISION, URHO3D_HANDLER(Main, HandleNodeCollision));
and the callback gets called whenever there is a collision:
void HandleNodeCollision(StringHash eventType, VariantMap& eventData) {
std::cout << "asdf" << std::endl;
}
but when I try the same for 2D, it never gets called.
Full runnable code below, tested with the following boilerplate: https://github.com/cirosantilli/Urho3D-cheat/blob/e2c955a45d8328fd5f8bf4df5685653452cb28a7/collision.cpp and Urho3D # 5e8a275:
#include <iostream>
#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Core/Object.h>
#include <Urho3D/Engine/Application.h>
#include <Urho3D/Engine/Engine.h>
#include <Urho3D/Engine/EngineDefs.h>
#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Graphics/DebugRenderer.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/Renderer.h>
#include <Urho3D/Input/Input.h>
#include <Urho3D/Input/InputEvents.h>
#include <Urho3D/Physics/PhysicsEvents.h>
#include <Urho3D/Scene/Scene.h>
#include <Urho3D/Scene/SceneEvents.h>
#include <Urho3D/Urho2D/CollisionBox2D.h>
#include <Urho3D/Urho2D/CollisionCircle2D.h>
#include <Urho3D/Urho2D/PhysicsWorld2D.h>
#include <Urho3D/Urho2D/RigidBody2D.h>
#include <Urho3D/Scene/Component.h>
using namespace Urho3D;
class Main : public Application {
URHO3D_OBJECT(Main, Application);
public:
Main(Context* context) : Application(context) {}
virtual void Setup() override {
engineParameters_[EP_FULL_SCREEN] = false;
engineParameters_[EP_WINDOW_TITLE] = __FILE__;
engineParameters_[EP_WINDOW_HEIGHT] = 512;
engineParameters_[EP_WINDOW_WIDTH] = 512;
}
void Start() {
auto windowWidth = 10.0f;
auto windowHeight = windowWidth;
auto groundWidth = windowWidth;
auto groundHeight = 1.0f;
auto ballRadius = 0.5f;
auto ballRestitution = 0.8f;
auto ballDensity = 1.0f;
// TODO: not working. Is there any way to avoid creating a custom
// Component as in the ragdoll example?
SubscribeToEvent(E_NODECOLLISION, URHO3D_HANDLER(Main, HandleNodeCollision));
SubscribeToEvent(E_POSTRENDERUPDATE, URHO3D_HANDLER(Main, HandlePostRenderUpdate));
SubscribeToEvent(E_KEYDOWN, URHO3D_HANDLER(Main, HandleKeyDown));
// Scene
this->scene_ = new Scene(this->context_);
this->scene_->CreateComponent<Octree>();
this->scene_->CreateComponent<DebugRenderer>();
this->scene_->CreateComponent<PhysicsWorld2D>();
auto physicsWorld = scene_->GetComponent<PhysicsWorld2D>();
physicsWorld->SetGravity(Vector2(0.0f, -10.0f));
// Graphics
auto cameraNode_ = this->scene_->CreateChild("Camera");
// Center of the camera.
cameraNode_->SetPosition(Vector3(0.0f, windowHeight / 2.0, -1.0f));
auto camera = cameraNode_->CreateComponent<Camera>();
camera->SetOrthographic(true);
camera->SetOrthoSize(windowWidth);
auto renderer = GetSubsystem<Renderer>();
SharedPtr<Viewport> viewport(new Viewport(context_, this->scene_, cameraNode_->GetComponent<Camera>()));
renderer->SetViewport(0, viewport);
// Ground
{
auto node = this->scene_->CreateChild("Ground");
node->SetPosition(Vector3(0.0f, groundHeight / 2.0f, 0.0f));
node->CreateComponent<RigidBody2D>();
auto collisionBox2d = node->CreateComponent<CollisionBox2D>();
collisionBox2d->SetSize(Vector2(groundWidth, groundHeight));
}
// Falling balls
{
auto nodeLeft = this->scene_->CreateChild("BallLeft");
{
auto& node = nodeLeft;
node->SetPosition(Vector3(-windowWidth / 4.0f, windowHeight / 2.0f, 0.0f));
auto body = node->CreateComponent<RigidBody2D>();
body->SetBodyType(BT_DYNAMIC);
auto collisionCircle2d = node->CreateComponent<CollisionCircle2D>();
collisionCircle2d->SetRadius(ballRadius);
collisionCircle2d->SetDensity(ballDensity);
collisionCircle2d->SetRestitution(ballRestitution);
}
auto nodeRight = nodeLeft->Clone();
nodeRight->SetPosition(Vector3(windowWidth / 4.0f, windowHeight * (3.0f / 4.0f), 0.0f));
}
}
void Stop() {}
private:
SharedPtr<Scene> scene_;
void HandleNodeCollision(StringHash eventType, VariantMap& eventData) {
std::cout << "asdf" << std::endl;
}
void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData) {
auto physicsWorld = this->scene_->GetComponent<PhysicsWorld2D>();
physicsWorld->DrawDebugGeometry();
}
void HandleKeyDown(StringHash /*eventType*/, VariantMap& eventData) {
using namespace KeyDown;
int key = eventData[P_KEY].GetInt();
if (key == KEY_ESCAPE) {
engine_->Exit();
}
}
};
URHO3D_DEFINE_APPLICATION_MAIN(Main);
The analogous runnable and working as expected 3D version can be found at: https://github.com/cirosantilli/Urho3D-cheat/blob/e2c955a45d8328fd5f8bf4df5685653452cb28a7/collision3d.cpp
The 2D event name is E_NODEBEGINCONTACT2D
Just replace E_NODECOLLISION with E_NODEUPDATECONTACT2D and it works.
Found at: https://discourse.urho3d.io/t/solved-help-with-collision-detection/1667
The names of all 2D events are present on this file: https://github.com/urho3d/Urho3D/blob/26ff4fce30bcc8f5a9f21e0e938d221cb2a53eaa/Source/Urho3D/Urho2D/PhysicsEvents2D.h#L35 they are:
E_PHYSICSUPDATECONTACT2D: during contact. Once for both bodies.
E_PHYSICSBEGINCONTACT2D: start of contact
E_PHYSICSENDCONTACT2D: end of contact
E_NODEUPDATECONTACT2D: during contact. Once for each body.
E_NODEBEGINCONTACT2D: begin contact
E_NODEENDCONTACT2D: end contact
Here is my updated working code, which also extracts collision information from the event: https://github.com/cirosantilli/Urho3D-cheat/blob/353d0353328fc4deb788336f740c7df00d3415f1/collision.cpp#L110

openCV:capture images from webcam but only greysreen

Can anyone tell me what's wrong with my code? I can use my webcam by other code, so there is nothing do with the supported problem. In my code below, I must set the camera index into a loop so that i can motivate my camera(the led inductor is on, simply set "CvCapture* camera=cvCaptureFromCAM(0)" can not run! that's wierd!).However, I just can obtain a greysreen,why?
#include "highgui.h"
#include "cv.h"
int main(int grac, char** grav)
{
CvCapture* camera;
int index;
for (index = -1; index <1; index++)
{
camera = cvCaptureFromCAM(index);
if (camera)
{
printf("%d\n", index);
IplImage* f;
cvNamedWindow("camera", CV_WINDOW_AUTOSIZE);
while (1)
{
f = cvQueryFrame(camera);
cvShowImage("camera", f);
char c = cvWaitKey(33);
if (c == 27)break;
}
}
}
cvReleaseCapture(&camera);
cvDestroyAllWindows;
}

CodeBook background subtraction with moving objects

I am trying to use CodeBook method for OpenCV to subtract the background. So far so good, but I am not sure if I can update the codebook for moving objects after some time span, say 5 minutes, I need to update the codebook after which I get lots of moving objects. How do I make sure that after 5 minutes I have a background that needs to be updated?
Thanks for the tips!
kim's algorithm supposedly has a cache layer, i did not dig deep enough into opencv implementation to know how to have a workable version that works with exposure problem.
notes
opencv book(which i havent read) should have the info you need if it's there at all
this is only 1 channel and not in yuv although it can be extended
needs more work on speed/testing (you can of course turn on optimization in compiler)
background subtraction is a buzzy word. try "change detection"
bgfg_cb.h
#ifndef __bgfg_cb_h__
#define __bgfg_cb_h__
//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.148.9778&rep=rep1&type=pdf
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <time.h>
using namespace cv;
using namespace std;
struct codeword {
float min;
float max;
float f;
float l;
int first;
int last;
bool isStale;
};
extern int alpha ;
extern float beta ;
extern int Tdel ,Tadd , Th;
void initializeCodebook(int w,int h);
void update_cb(Mat& frame);
void fg_cb(Mat& frame,Mat& fg);
#endif
bgfg_cb.cpp
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <time.h>
#include "bgfg_cb.h"
using namespace cv;
using namespace std;
vector<codeword> **cbMain;
vector<codeword> **cbCache;
int t=0;
int alpha = 10;//knob
float beta =1;
int Tdel = 200,Tadd = 150, Th= 200;//knobs
void initializeCodebook(int w,int h)
{
cbMain = new vector<codeword>*[w];
for(int i = 0; i < w; ++i)
cbMain[i] = new vector<codeword>[h];
cbCache = new vector<codeword>*[w];
for(int i = 0; i < w; ++i)
cbCache[i] = new vector<codeword>[h];
}
void update_cb(Mat& frame)
{
if(t>10) return;
for(int i=0;i<frame.rows;i++)
{
for(int j=0;j<frame.cols;j++)
{
int pix = frame.at<uchar>(i,j);
vector<codeword>& cm =cbMain[i][j];
bool found = false;
for(int k=0;k<cm.size();k++)
{
if(cm[k].min<=pix && pix<=cm[k].max && !found)
{
found=true;
cm[k].min = ((pix-alpha)+(cm[k].f*cm[k].min))/(cm[k].f+1);
cm[k].max = ((pix+alpha)+(cm[k].f*cm[k].max))/(cm[k].f+1);
cm[k].l=0;
cm[k].last=t;
cm[k].f++;
}else
{
cm[k].l++;
}
}
if(!found)
{
codeword n={};
n.min=max(0,pix-alpha);
n.max=min(255,pix+alpha);
n.f=1;
n.l=0;
n.first=t;
n.last=t;
cm.push_back(n);
}
}
}
t++;
}
void fg_cb(Mat& frame,Mat& fg)
{
fg=Mat::zeros(frame.size(),CV_8UC1);
if(cbMain==0) initializeCodebook(frame.rows,frame.cols);
if(t<10)
{
update_cb(frame);
return;
}
for(int i=0;i<frame.rows;i++)
{
for(int j=0;j<frame.cols;j++)
{
int pix = frame.at<uchar>(i,j);
vector<codeword>& cm = cbMain[i][j];
bool found = false;
for(int k=0;k<cm.size();k++)
{
if(cm[k].min<=pix && pix<=cm[k].max && !found)
{
cm[k].min = ((1-beta)*(pix-alpha)) + (beta*cm[k].min);
cm[k].max = ((1-beta)*(pix+alpha)) + (beta*cm[k].max);
cm[k].l=0;
cm[k].first=t;
cm[k].f++;
found=true;
}else
{
cm[k].l++;
}
}
cm.erase( remove_if(cm.begin(), cm.end(), [](codeword& c) { return c.l>=Tdel;} ), cm.end() );
fg.at<uchar>(i,j) = found?0:255;
if(found) continue;
found = false;
vector<codeword>& cc = cbCache[i][j];
for(int k=0;k<cc.size();k++)
{
if(cc[k].min<=pix && pix<=cc[k].max && !found)
{
cc[k].min = ((1-beta)*(pix-alpha)) + (beta*cc[k].min);
cc[k].max = ((1-beta)*(pix+alpha)) + (beta*cc[k].max);
cc[k].l=0;
cc[k].first=t;
cc[k].f++;
found=true;
}else
{
cc[k].l++;
}
}
if(!found)
{
codeword n={};
n.min=max(0,pix-alpha);
n.max=min(255,pix+alpha);
n.f=1;
n.l=0;
n.first=t;
n.last=t;
cc.push_back(n);
}
cc.erase( remove_if(cc.begin(), cc.end(), [](codeword& c) { return c.l>=Th;} ), cc.end() );
for(vector<codeword>::iterator it=cc.begin();it!=cc.end();it++)
{
if(it->f>Tadd)
{
cm.push_back(*it);
}
}
cc.erase( remove_if(cc.begin(), cc.end(), [](codeword& c) { return c.f>Tadd;} ), cc.end() );
}
}
}
main.cpp
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "bgfg_cb.h"
#include <iostream>
using namespace cv;
using namespace std;
void proc()
{
Mat frame,fg,gray;
VideoCapture cap("C:/Downloads/S2_L1.tar/S2_L1/Crowd_PETS09/S2/L1/Time_12-34/View_001/frame_%04d.jpg");
cap >> frame;
initializeCodebook(frame.rows,frame.cols);
for(;;)
{
cap>>frame;
cvtColor(frame,gray,CV_BGR2GRAY);
fg_cb(gray,fg);
Mat cc;
imshow("fg",fg);
waitKey(1);
}
}
int main(int argc, char ** argv)
{
proc();
cin.ignore(1);
return 0;
}

Resources