Convert pixel value to distance - orbbec

I got the Orbbec camera.
I use C#.
I have the C# wrapper for their SDK.
I have the depth stream and can get images from that stream. But, how do I convert the pixel value to distance (in mms)?
I have looked around ie Googling and I have emailed the Orbbec people.
So far my code:
private void HandleDepthFrame(
Astra.ReaderFrame frame )
{
var depthFrame = frame.GetFrame<Astra.DepthFrame>();
if ( depthBuffer.Update( depthFrame ) )
{
BitmapSource image = depthBuffer.ImageSource;
dispatcher.BeginInvoke(DispatcherPriority.DataBind, new Action(() => getBitmap(image)));
if ( frameRateCalculator.RegisterFrame() )
RaisePropertyChanged( nameof(FramesPerSecond) );
}
}
private void getBitmap(BitmapSource source)
{
Bitmap bmp = new Bitmap(source.PixelWidth, source.PixelHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
source.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
bmp.UnlockBits(data);
Image<Gray, int16> imageCV = new Image<Gray, int16>(bmp);
??how to read and trsanslate the mat data to distance?
}
Thanks

I use the C++ setup for astra and I was able to achieve this by using some code in the demos they provide in the Guide. This code here:
int main(int argc, char** argv)
{
while (window.isOpen())
{
astra_update();
sf::Event event;
while (window.pollEvent(event))
{
switch (event.type)
{
case sf::Event::MouseMoved:
{
auto coordinateMapper = depthStream.coordinateMapper();
listener.update_mouse_position(window, coordinateMapper);
}break;
}
}
}
}
void update_mouse_position(sf::RenderWindow& window,
const astra::CoordinateMapper& coordinateMapper)
{
const sf::Vector2i position = sf::Mouse::getPosition(window);
const sf::Vector2u windowSize = window.getSize();
float mouseNormX = position.x / float(windowSize.x);
float mouseNormY = position.y / float(windowSize.y);
mouseX_ = depthWidth_ * mouseNormX;
mouseY_ = depthHeight_ * mouseNormY;
if (mouseX_ >= depthWidth_ ||
mouseY_ >= depthHeight_ ||
mouseX_ < 0 ||
mouseY_ < 0) { return; }
const size_t index = (depthWidth_ * mouseY_ + mouseX_);
const short z = depthData_[index];
coordinateMapper.convert_depth_to_world(float(mouseX_),
float(mouseY_),
float(z),
mouseWorldX_,
mouseWorldY_,
mouseWorldZ_);
}
So in this demo you can actually see the values in depth being showned and using this sample code its possible to manipulate them to our favor.
Hope this helps.

Related

dropdown error on device in codenameone

I am implementing drop-drown feature in my app. Its implemented using container with list of elements in it.
Suppose the drop down list has following items aa1, aa2, aa3, aa4 aa5 and so on. And if i search as 'aa' it displays items starting from 'aa', if I select aa5 from list, it takes aa1 and displays that. But whereas if I scroll the items and select its working fine. This problem occurring only on iOS device working perfectly fine on simulator.
the first picture depicts how drop down looks like, in second picture if I search 'ee', it gives list of items starting with 'ee'. If I select 'ee5', it sets to ee1 as shown in picture 3. Problem only on device. Any workaround for this?
So, please let me know whats the issue with this.
Thanks
[![enter image description here][1]][1]
private CustomList itemList;
class CustomList extends List {
int startYPos = -1;
long lastDiff = 0;
Timer t = null;
int draggingState = 0;
public CustomList() {
this.setTensileDragEnabled(false);
}
}
private class ButtonListener implements ActionListener {
public void actionPerformed(final ActionEvent evt) {
final Runnable rn = new Runnable() {
public void run() {
// Create and show a dialog to allow users to make a selection.
final UiBuilder uib = dm.UiBuilder();
dialog = (Dialog) uib.createContainer(DESIGNER_NAME_DIALOG_COMBOBOX_CONTAINER);
GenericSpinner itemSpinner = (GenericSpinner) uib.findByName(DESIGNER_NAME_DIALOG_COMBOBOX_GENERIC_SPINNER, dialog);
itemSpinner.setPreferredW(Display.getInstance().getDisplayWidth() * 4 / 5);
//remove from parent and replace with a linear list
Container parent = itemSpinner.getParent();
parent.removeComponent(itemSpinner);
// Add the searchable text field box
final TextField tf = (TextField)uib.findByName("Search", dialog);
tf.addDataChangedListener(new DataChangedListener() {
#Override
public void dataChanged(int type, int index) {
Object[] items = model.getFilteredItems(tf.getText());
itemList.setModel(new DefaultListModel(items));
}
});
itemList = new CustomList();
itemList.getAllStyles().setBgTransparency(0);
itemList.setItemGap(0);
parent.addComponent(BorderLayout.CENTER, itemList);
final String[] items = model.getItems();
itemList.setModel(new DefaultListModel(items));
itemList.getStyle().setMargin(10, 10, 10, 10);
itemList.setFireOnClick(true);
itemList.setLongPointerPressActionEnabled(false);
ActionListener list = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (model.isUserEditable() && model.getItemCount() > 0) {
int i = itemList.getSelectedIndex();
if (i > items.length - 1) {
return;
}
itemList.getModel().setSelectedIndex(i);
model.onUserDataEntered((String) itemList.getModel().getItemAt(i));
String textToDisplay = (String) itemList.getModel().getItemAt(i);
button.setText(textToDisplay);
}
dialog.dispose();
}
};
itemList.addActionListener(list);
CommonTransitions tran = CommonTransitions.createEmpty();
dialog.setTransitionInAnimator(tran);
dialog.setTransitionOutAnimator(tran);
itemList.setRenderer(new ListRenderer());
//related to dialog to show list of items
//how much space do we really need???
if (cellHeight == 0) {
int dip = Display.getInstance().convertToPixels(1);
int siz = 2;
if (Display.getInstance().isTablet()) {
siz = 4;
}
siz *= 2;
cellHeight = siz * dip;
}
int heightRequired = cellHeight * (items.length + 8);
//is this too much for the screen - we will use 3/4 of the screen height max
int availableHeight = Display.getInstance().getDisplayHeight() * 3;
availableHeight /= 4;
if (heightRequired > availableHeight) {
int topPos = Display.getInstance().getDisplayHeight() / 8;
int bottomPos = topPos + availableHeight;
dialog.show(topPos, topPos, 40, 40);
}
else {
int topPos = (Display.getInstance().getDisplayHeight() - heightRequired) / 2;
int bottomPos = topPos + heightRequired;
dialog.show(topPos, topPos, 40, 40);
}
}
};
}
}
//new code using Multibutton implementation
final String[] listItems = model.getItems();
Display.getInstance().callSerially(() ->{
multiButton= new MultiButton();
multiButton.setTextLine1(s);
dialog.add(multiButton);
multiButton.addActionListener(e -> Log.p("you picked " + multiButton.getSelectCommandText(), Log.ERROR));
}
dialog.revalidate();
});
I would recommend using a Container and simple layout search as demonstrated by code such as this. The code below was taken from the Toolbar javadoc:
Image duke = null;
try {
duke = Image.createImage("/duke.png");
} catch(IOException err) {
Log.e(err);
}
int fiveMM = Display.getInstance().convertToPixels(5);
final Image finalDuke = duke.scaledWidth(fiveMM);
Toolbar.setGlobalToolbar(true);
Form hi = new Form("Search", BoxLayout.y());
hi.add(new InfiniteProgress());
Display.getInstance().scheduleBackgroundTask(()-> {
// this will take a while...
Contact[] cnts = Display.getInstance().getAllContacts(true, true, true, true, false, false);
Display.getInstance().callSerially(() -> {
hi.removeAll();
for(Contact c : cnts) {
MultiButton m = new MultiButton();
m.setTextLine1(c.getDisplayName());
m.setTextLine2(c.getPrimaryPhoneNumber());
Image pic = c.getPhoto();
if(pic != null) {
m.setIcon(fill(pic, finalDuke.getWidth(), finalDuke.getHeight()));
} else {
m.setIcon(finalDuke);
}
hi.add(m);
}
hi.revalidate();
});
});
hi.getToolbar().addSearchCommand(e -> {
String text = (String)e.getSource();
if(text == null || text.length() == 0) {
// clear search
for(Component cmp : hi.getContentPane()) {
cmp.setHidden(false);
cmp.setVisible(true);
}
hi.getContentPane().animateLayout(150);
} else {
text = text.toLowerCase();
for(Component cmp : hi.getContentPane()) {
MultiButton mb = (MultiButton)cmp;
String line1 = mb.getTextLine1();
String line2 = mb.getTextLine2();
boolean show = line1 != null && line1.toLowerCase().indexOf(text) > -1 ||
line2 != null && line2.toLowerCase().indexOf(text) > -1;
mb.setHidden(!show);
mb.setVisible(show);
}
hi.getContentPane().animateLayout(150);
}
}, 4);
hi.show();

Processing: webcam save and playback bug

I should be beyond this, but I can't get to the bottom of this error. I'm trying to write a sketch that records the feed of my Mac camera and stores each recording "session" into a PImage array, then adds that to a list of sessions (a PImage[] ArrayList). I'm using a 'Replay' class to access the images stored in memory to and replay them at a random position. The code below should be ready to be copied straight into the IDE.
Any help would be greatly appreciated. I have no idea why the replay objects are always displaying the live image. Thanks!
import processing.video.*;
Capture cam;
ArrayList<PImage[]> allImages;
ArrayList<PImage> currentImages;
ArrayList<Replay> replays;
boolean recording = false;
boolean finishedSaving = true;
int currentIndex = 0;
void setup() {
size(1056, 704, P2D);
frameRate(30);
allImages = new ArrayList<PImage[]>();
currentImages = new ArrayList<PImage>();
replays = new ArrayList<Replay>();
String[] cams = Capture.list();
if (cams.length == 0) {
println("No cams!");
exit();
} else {
cam = new Capture(this, 1056, 704, cams[0], 30);
cam.start();
}
}
void draw() {
background(0);
if (cam.available() == true) {
cam.read();
}
for (Replay r : replays) {
r.display();
}
if (recording) {
currentImages.add(cam);
noFill();
stroke(255, 0, 0);
strokeWeight(5);
rect(0, 0, cam.width/3, cam.height/3);
} else {
saveToArray();
}
image(cam, 0, 0, cam.width/3, cam.height/3);
}
void saveToArray() {
if (!finishedSaving) {
PImage[] tempImages = currentImages.toArray(new PImage[currentImages.size()]);
allImages.add(tempImages);
currentImages.clear();
println("Finished saving to allImages array");
println("allImages array size now = " + allImages.size());
replays.add(new Replay(currentIndex));
println("Added new Replay (index: " + currentIndex + ")");
currentIndex++;
finishedSaving = true;
println();
}
}
void keyPressed() {
if (key == 'r' || key == 'R') {
recording = !recording;
println("Recording: " + recording);
finishedSaving = false;
}
}
class Replay {
PVector position;
float w, h;
PImage[] images;
int count;
Replay(int allImagesIndex) {
w = cam.width/3;
h = cam.height/3;
position = new PVector(random(width-w), random(height-h));
count = 1;
images = allImages.get(allImagesIndex);
}
void display() {
image(images[count], position.x, position.y, w, h);
count++;
if (count > images.length-1) count = 1;
}
}
Looks like this was due to the camera feed always being assignment to each individual image. To get a "copy" of the "current" video stream frame, I just added .get() to the feed so it fetches the pixels and stores them in a PImage variable.
currentImages.add(cam.get());

(Processing) Removing Previously Used Object in Array

Sorry for the horrible wording of the title. I'm creating a game of "War" in Processing for my Programming class. I need to change my code so that each card that is used is removed from the deck/array. I stumbled upon some posts and Google results mentioning "ArrayList", but I'm still sort of clueless.
The following code displays two separate, random cards and displays two new random cards when the mouse is clicked.
(First Tab 'War')
void draw(){
image(card[imageIndex],40,150);
image(card2[imageIndex2],340,150);
}
void mousePressed(){
imageIndex = int(random(card.length));
imageIndex2 = int(random(card2.length));
}
(Second Tab 'Card')
PImage[] card = new PImage[13];
PImage[] card2 = new PImage[13];
int imageIndex = int(random(0,12)),
imageIndex2 = int(random(0,12));
void setup(){
size(500,500);
card[0] = loadImage("2_of_clubs.jpg");
card[1] = loadImage("3_of_clubs.jpg");
card[2] = loadImage("4_of_clubs.jpg");
card[3] = loadImage("5_of_clubs.jpg");
card[4] = loadImage("6_of_clubs.jpg");
card[5] = loadImage("7_of_clubs.jpg");
card[6] = loadImage("8_of_clubs.jpg");
card[7] = loadImage("9_of_clubs.jpg");
card[8] = loadImage("10_of_clubs.jpg");
card[9] = loadImage("jack_of_clubs.jpg");
card[10] = loadImage("queen_of_clubs.jpg");
card[11] = loadImage("king_of_clubs.jpg");
card[12] = loadImage("ace_of_clubs.jpg");
card2[0] = loadImage("2_of_clubs.jpg");
card2[1] = loadImage("3_of_clubs.jpg");
card2[2] = loadImage("4_of_clubs.jpg");
card2[3] = loadImage("5_of_clubs.jpg");
card2[4] = loadImage("6_of_clubs.jpg");
card2[5] = loadImage("7_of_clubs.jpg");
card2[6] = loadImage("8_of_clubs.jpg");
card2[7] = loadImage("9_of_clubs.jpg");
card2[8] = loadImage("10_of_clubs.jpg");
card2[9] = loadImage("jack_of_clubs.jpg");
card2[10] = loadImage("queen_of_clubs.jpg");
card2[11] = loadImage("king_of_clubs.jpg");
card2[12] = loadImage("ace_of_clubs.jpg");
}
Using ArrayList would look more or less like:
// gonna use strings instead of images
// just to show the idea. I don't have all this images...
ArrayList<String> card = new ArrayList<String>();
ArrayList<String> card2;
int imageIndex, imageIndex2;
String display1, display2;
void setup() {
size(500, 500);
card.add("2_of_clubs.jpg");
card.add("3_of_clubs.jpg");
card.add("4_of_clubs.jpg");
card.add("5_of_clubs.jpg");
card.add("6_of_clubs.jpg");
card.add("7_of_clubs.jpg");
card.add("8_of_clubs.jpg");
card.add("9_of_clubs.jpg");
card.add("10_of_clubs.jpg");
card.add("jack_of_clubs.jpg");
card.add("queen_of_clubs.jpg");
card.add("king_of_clubs.jpg");
card.add("ace_of_clubs.jpg");
card2 = new ArrayList<String>(card);
imageIndex = int(random(card.size()));
imageIndex2 = int(random(card2.size()));
display1 = card.get(imageIndex);
display2 = card2.get(imageIndex2);
card.remove(imageIndex);
card2.remove(imageIndex2);
println("\ncard draw from card : "+ display1);
println("card draw from card2: "+ display2 + "\n");
}
void draw() {
}
void mousePressed() {
if (card.size() > 0) {
imageIndex = int(random(card.size()));
imageIndex2 = int(random(card2.size()));
display1 = card.get(imageIndex);
display2 = card2.get(imageIndex2);
card.remove(imageIndex);
card2.remove(imageIndex2);
println("\ncard draw from card : "+ display1);
println("card draw from card2: "+ display2 + "\n");
} else {
println("The deck is empty...");
}
}
if you have to use arrays then you would have to do something similar to the following code:
PImage[] removeCardFromDeck(PImage deck, int index){
PImage[] newdeck = new PImage[deck.length -1];
int count=0;
for(int i =0 ; i<newdeck.length;i++){
if(count==index) count++;
newdeck[i] = deck[count];
count++;
}
return newdeck;
}
but for this task it is better to use ArrayLists.

caching and rendering spritesheets doesn't work

I'd like to cache my spritesheet (tilesheet) into an array. I do this because every spritesheet shall be cached inside of an array so my objects can pull their tiles from them easily. But my cache doesn't seem to work because absolutely nothing gets rendered out of it. I can't see anything.
There is something inside my cache (likely bitmapData) and it is not null so currently I don't know where the problem might be.
Can someone help me out with this issue, please?
this function shall render each tile of an array to a background via copypixels
public function renderCachedTile(canvasBitmapData:BitmapData, tileArray:Array):void
{
tileCache = tileArray;
tileArray = [];
x = nextX;
y = nextY;
point.x = x;
point.y = y;
tileRect.x = tileWidth;
tileRect.y = tileHeight;
if (animationCount >= animationDelay)
{
animationCount = 0;
if(reverse)
{
currentTile--;
if (currentTile < 1)
{
currentTile = tilesLength - 1;
}
} else {
currentTile++;
if (currentTile >= tilesLength - 1)
{
currentTile = 0;
}
}
} else {
animationCount++;
}
canvasBitmapData.lock();
canvasBitmapData.copyPixels(tileCache[currentTile], tileRect, point);
canvasBitmapData.unlock();
}
this function 'separates' my spritesheet into tiles and throws them into an array
private function tileToCache():void {
var tileBitmapData:BitmapData = new BitmapData(tileWidth, tileHeight, true, 0x00000000);
var tilePt:Point = new Point(0, 0);
var tileRect:Rectangle = new Rectangle;
tileCache = [];
for (var tileCtr:int = 0; tileCtr < tilesLength; tileCtr++) {
tileBitmapData.lock();
tileRect.x = int((tileCtr % spritesPerRow)) * tileWidth;
tileRect.y = int((tileCtr / spritesPerRow)) * tileHeight;
tileBitmapData.copyPixels(tileSheet, tileRect, tilePt);
tileBitmapData.unlock();
tileCache.push(tileBitmapData);
}
}
Unless there is code missing from your example, in your tileToCache you instantiate and use tileRect without defining a width and height:
private function tileToCache():void {
var tileRect:Rectangle = new Rectangle;
/* ... */
tileBitmapData.copyPixels(tileSheet, tileRect, tilePt);
If your source was at 0, 0 I presume you would want:
var tileRect:Rectangle = new Rectangle(0, 0, tileWidth, tileHeight);

how to deform an ellipse in running time

i first sorry about my english,i´ll try to explain want i want to do
i need to draw an ellipse with wpf that represents an aura and it´s "deformations" representing problematic zones in it,in short an ellipse that can be deformed in running time in specific points
I'm trying to draw several bezier curves forming an ellipse but it´t very difficult (and i don´t know how) to make points that can be dragged forming convex or hollow zones in that ellipse.
¿i made myselft clear in my spanglish? ¿is there an easy way to do that?
Thanks in advance
I don't know what exactly you are trying to do but I recommend making a high resolution version of the ellipse and keeping track of the deformations yourself. Here is a sample program to get you started.
For this demo the XAML is simple:
<Canvas Name="canvas" Focusable="True" KeyDown="canvas_KeyDown" MouseDown="canvas_MouseDown" MouseMove="canvas_MouseMove" MouseUp="canvas_MouseUp"/>
and a the code-behind:
public partial class EllipseDemo : Window
{
const int resolution = 1000;
const double major = 150;
const double minor = 100;
const double xOrigin = 200;
const double yOrigin = 200;
const double radius = 10;
const double scale = 0.1;
const double spread = 10;
const double magnitude = 10;
Path path;
Ellipse controlPoint;
LineSegment[] segments;
double[] deformation;
double[] perturbation;
int controlPointIndex;
public EllipseDemo()
{
InitializeComponent();
segments = new LineSegment[resolution];
deformation = new double[resolution];
perturbation = new double[resolution];
for (int i = 0; i < resolution; i++)
{
var x = i >= resolution / 2 ? i - resolution : i;
perturbation[i] = magnitude * Math.Exp(-Math.Pow(scale * x, 2) / spread);
}
path = new Path();
path.Stroke = new SolidColorBrush(Colors.Black);
path.StrokeThickness = 5;
CalculateEllipse();
canvas.Children.Add(path);
controlPoint = new Ellipse();
controlPoint.Stroke = new SolidColorBrush(Colors.Red);
controlPoint.Fill = new SolidColorBrush(Colors.Transparent);
controlPoint.Width = 2 * radius;
controlPoint.Height = 2 * radius;
MoveControlPoint(0);
canvas.Children.Add(controlPoint);
canvas.Focus();
}
void CalculateEllipse()
{
for (int i = 0; i < resolution; i++)
{
double angle = 2 * Math.PI * i / resolution;
double x = xOrigin + Math.Cos(angle) * (major + deformation[i]);
double y = yOrigin + Math.Sin(angle) * (minor + deformation[i]);
segments[i] = new LineSegment(new Point(x, y), true);
}
var figure = new PathFigure(segments[0].Point, segments, true);
var figures = new PathFigureCollection();
figures.Add(figure);
var geometry = new PathGeometry();
geometry.Figures = figures;
path.Data = geometry;
}
void MoveControlPoint(int index)
{
controlPointIndex = index;
Canvas.SetLeft(controlPoint, segments[index].Point.X - radius);
Canvas.SetTop(controlPoint, segments[index].Point.Y - radius);
}
bool mouseDown;
void canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
if (Mouse.DirectlyOver != controlPoint)
return;
mouseDown = true;
controlPoint.CaptureMouse();
}
void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (!mouseDown)
return;
int index = FindNearestIndex(e.GetPosition(canvas));
MoveControlPoint(index);
}
void canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
if (!mouseDown)
return;
controlPoint.ReleaseMouseCapture();
mouseDown = false;
}
private void canvas_KeyDown(object sender, KeyEventArgs e)
{
int delta = 0;
switch (e.Key)
{
case Key.Up:
delta = 1;
break;
case Key.Down:
delta = -1;
break;
}
if (delta == 0)
return;
int index = controlPointIndex;
for (int i = 0; i < resolution; i++)
deformation[(i + index) % resolution] += delta * perturbation[i];
CalculateEllipse();
MoveControlPoint(index);
}
int FindNearestIndex(Point point)
{
var min = double.PositiveInfinity;
var index = -1;
for (int i = 0; i < segments.Length; i++)
{
var vector = point - segments[i].Point;
var distance = vector.LengthSquared;
if (distance < min)
{
index = i;
min = distance;
}
}
return index;
}
}
This works mostly with a Path represented by line segments and an Ellipse as a control point. The mouse can move the control point around the ellipse and then the arrow keys add or remove a canned perturbation. Everything is hard coded but if you are OK with the math then it should help you get started.
Here's the program in action:

Resources