Creating Terrain Map with SRTM HGT File - ios

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

Related

Lua mount filesystem

I want to mount a filesystem on Linux using Lua, but I haven't found any capability in the lua 5.4 manual or the LuaFileSytem library. Is there some way to mount a filesystem in Lua or with an existing library?
Like most platform-dependent syscall, Lua won't provide such mapping out of the box.
So you'll need some C-API module that does the trick.
Looks like https://github.com/justincormack/ljsyscall is generic "but" focused on LuaJIT and https://luaposix.github.io/luaposix/ doesn't provide mount.
I recently had similar needs, and I ended doing the C module:
static int l_mount(lua_State* L)
{
int res = 0;
// TODO add more checks on args!
const char *source = luaL_checkstring(L, 1);
const char *target = luaL_checkstring(L, 2);
const char *type = luaL_checkstring(L, 3);
lua_Integer flags = luaL_checkinteger(L, 4);
const char *data = luaL_checkstring(L, 5);
res = mount(source, target, type, flags, data);
if ( res != 0)
{
int err = errno;
lua_pushnil(L);
lua_pushfstring(L, "mount failed: errno[%s]", strerror(err));
return 2;
}
else
{
lua_pushfstring(L, "ok");
return 1;
}
}
#define register_constant(s)\
lua_pushinteger(L, s);\
lua_setfield(L, -2, #s);
// Module functions
static const luaL_Reg R[] =
{
{ "mount", l_mount },
{ NULL, NULL }
};
int luaopen_sysutils(lua_State* L)
{
luaL_newlib(L, R);
// do more mount defines mapping, maybe in some table.
register_constant(MS_RDONLY);
//...
return 1;
}
Compile this as a C Lua module, and don't forget that you need CAP_SYS_ADMIN to call mount syscall.

How to turn on LED that's attached to an arduino via BLE from ios app?

Here is the scenario. I have an esp32, 2 led's and a ios example app I found online here. Currently If I press a button on my esp32 it notifies the ios app to display "1", if pressed again it displays "0". This works perfectly.
The tricky part is that this ios app allows me to send a write command to the esp32. I'd like to make it so if '1' is sent LED A turns ON and LED B turns OFF, then LED A OFF and LED B ON when 0 is sent. I am unable to do this though. Try as I might I can't figure out where in the chain of this project something is wrong. Maybe the code on the esp32 or maybe the app i'm unsure.
Here is my arduino code. (There is more to the code not mentioned, I actually have 4 led's but I only want to turn on 2 certain ones when a write command is sent).
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
bool oldDeviceConnected = false;
boolean oldState = LOW;
uint32_t value = 0;
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++) {
Serial.print(rxValue[i]);
}
Serial.println();
if (rxValue.find("1") != -1) {
digitalWrite(13, HIGH);
digitalWrite(27, LOW);
}
else if (rxValue.find("0") != -1) {
digitalWrite(13, LOW);
digitalWrite(27, HIGH);
}
}
}
};
const int bt1 = 14;
boolean bt1g = true;
int bt1t = 0;
void setup() {
pinMode(13, OUTPUT);
pinMode(15, OUTPUT);
pinMode(33, OUTPUT);
pinMode(27, OUTPUT);
pinMode(bt1, INPUT_PULLUP);
Serial.begin(9600);
BLEDevice::init("ESP32");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY
);
pCharacteristic->addDescriptor(new BLE2902());
pService->start();
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(false);
pAdvertising->setMinPreferred(0x0);
BLEDevice::startAdvertising();
Serial.println("Waiting a client connection to notify...");
}
void loop()
{
if (bt1g) {
if (digitalRead(bt1) == LOW ) {
bt1t = (bt1t + 1) % 2;
Serial.println(bt1t);
bt1g = false;
}
}
if (!bt1g) {
if (digitalRead(bt1) == HIGH) {
bt1g = true;
}
}
if (bt1t == 0) {
digitalWrite(15, LOW);
digitalWrite(33, HIGH);
}
}
boolean newState = digitalRead(15);
if (deviceConnected) {
if (newState != oldState) {
if (newState == LOW) {
pCharacteristic->setValue("1");
}
else {
pCharacteristic->setValue("0");
}
pCharacteristic->notify();
};
oldState = newState;
}
delay(50);
}
It looks like the entire code for the ios app is too long to submit to this post so here is the github
I'm really unsure and stuck in a rut. Any help is appreciated!
Could it be you are not discovering the correct characteristics? It looks like you only have one service and one characteristic.

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

Contour position with "findcontour" opencv on processing

I'm working on a project where I have to use a webcam, an arduino, a raspberry and an IR proximity sensor. I arrived to do everything with some help of google. But I have a big problem that's really I think.
I'm using OpenCV library on processing and I'd like the contours that get by the webcam be in the center of the sketch. But All only arrived to move the video and not the contours here's my code.
I hope you'll could help me :)
All the best
Alexandre
////////////////////////////////////////////
////////////////////////////////// LIBRARIES
////////////////////////////////////////////
import processing.serial.*;
import gab.opencv.*;
import processing.video.*;
/////////////////////////////////////////////////
////////////////////////////////// INITIALIZATION
/////////////////////////////////////////////////
Movie mymovie;
Capture video;
OpenCV opencv;
Contour contour;
////////////////////////////////////////////
////////////////////////////////// VARIABLES
////////////////////////////////////////////
int lf = 10; // Linefeed in ASCII
String myString = null;
Serial myPort; // The serial port
int sensorValue = 0;
int x = 300;
/////////////////////////////////////////////
////////////////////////////////// VOID SETUP
/////////////////////////////////////////////
void setup() {
size(1280, 1024);
// List all the available serial ports
printArray(Serial.list());
// Open the port you are using at the rate you want:
myPort = new Serial(this, Serial.list()[1], 9600);
myPort.clear();
// Throw out the first reading, in case we started reading
// in the middle of a string from the sender.
myString = myPort.readStringUntil(lf);
myString = null;
opencv = new OpenCV(this, 720, 480);
video = new Capture(this, 720, 480);
mymovie = new Movie(this, "visage.mov");
opencv.startBackgroundSubtraction(5, 3, 0.5);
mymovie.loop();
}
////////////////////////////////////////////
////////////////////////////////// VOID DRAW
////////////////////////////////////////////
void draw() {
image(mymovie, 0, 0);
image(video, 20, 20);
//tint(150, 20);
noFill();
stroke(255, 0, 0);
strokeWeight(1);
// check if there is something new on the serial port
while (myPort.available() > 0) {
// store the data in myString
myString = myPort.readStringUntil(lf);
// check if we really have something
if (myString != null) {
myString = myString.trim(); // let's remove whitespace characters
// if we have at least one character...
if (myString.length() > 0) {
println(myString); // print out the data we just received
// if we received a number (e.g. 123) store it in sensorValue, we sill use this to change the background color.
try {
sensorValue = Integer.parseInt(myString);
}
catch(Exception e) {
}
}
}
}
if (x < sensorValue) {
video.start();
opencv.loadImage(video);
}
if (x > sensorValue) {
image(mymovie, 0, 0);
}
opencv.updateBackground();
opencv.dilate();
opencv.erode();
for (Contour contour : opencv.findContours()) {
contour.draw();
}
}
//////////////////////////////////////////////
////////////////////////////////// VOID CUSTOM
//////////////////////////////////////////////
void captureEvent(Capture video) {
video.read(); // affiche l'image de la webcam
}
void movieEvent(Movie myMovie) {
myMovie.read();
}
One approach you could use is to call the translate() function to move the origin of the canvas before you call contour.draw(). Something like this:
translate(moveX, moveY);
for (Contour contour : opencv.findContours()) {
contour.draw();
}
What you use for moveX and moveY depends entirely on exactly what you're trying to do. You might use whatever position you're using to draw the video (if you want the contours displayed on top of the video), or you might use width/2 and height/2 (maybe minus a bit to really center the contours).
More info can be found in the reference. Play with a bunch of different values, and post an MCVE if you get stuck. Good luck.

Using videoGrabber with ofMesh in OpenFrameworks on 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?

Resources