Can I get some examples about pointclouds with ARCore? I really search it for days.
Currently I am working on an application similar to this one:This app
Has the feature to view pcl and save files in .ply format
Thanks
The HelloARSample app renders pointcloud in a scene. You can get the coordinates for each point and save them manually in a .ply format.
To get a point cloud, you can create a float buffer and add the points from each frame.
FloatBuffer myPointCloud = FloatBuffer.allocate(capacity);
Session session = new Session(context);
Frame frame = session.update();
try (PointCloud ptcld = frame.acquirePointCloud()) {
myPointCloud.put(ptcld.getPoints());
}
The float buffer saves the points like [x1,x1,z1,confidence1, x2,x2,z2,confidence2, ...].
I havent looked at .ply file struckture, but if you want to save it to a .pcd file, you must create a header, then insert a point per line. Here is a detailed explanation on how to do it.
I did it like this
private boolean savePointCloudFile() {
String data = "";
String fileName = "pointCloud";
int points = 0;
String holder = "";
// Write the point cloud data by iterating over each point:
for (int i=0; i<pointCloud.position(); i+=4) {
data += pointCloud.get(i) + " " + // x
pointCloud.get(i + 1) + " " + // y
pointCloud.get(i + 2) + " " + // z
pointCloud.get(i + 3) + "\n"; // confidence
points = i;
}
points = points / 4 - 10; // Removed last 10 points to prevent errors in case that I lost points
// Write file header
data = "# .PCD v.7 - Point Cloud Data file format\n" +
"VERSION .7\n" +
"FIELDS x y z rgb\n" + // confidence represented by rgb
"SIZE 4 4 4 4\n" + // you only have 3 values xyz
"TYPE F F F F\n" + // all floats
"COUNT 1 1 1 1\n" +
"WIDTH " + points + "\n" +
"HEIGHT 1\n" +
"VIEWPOINT 0 0 0 1 0 0 0\n" +
"POINTS " + points + "\n" +
"DATA ascii \n" + data;
//BufferedWriter out = new BufferedWriter(new FileWriter(new File(new File(Environment.getExternalStoragePublicDirectory(
// Environment.DIRECTORY_DOCUMENTS), fileName + ".pcd"));
try {
File file = new File(context.getExternalFilesDir(null), fileName +".pcd");
FileOutputStream stream = new FileOutputStream(file);
file.createNewFile();
//FileOutputStream out = new FileOutputStream(file);
stream.write(data.getBytes());
stream.close();
Log.i("SUCCESS", "File saved successfully in " + file.getAbsolutePath());
return true;
} catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
return false;
}
}
You should save the file from within a separate thread as it may cause a timeout error, because it takes too long to save so many points to a file.
You should get a file similar to this
# .PCD v.7 - Point Cloud Data file format
VERSION .7
FIELDS x y z rgb
SIZE 4 4 4 4
TYPE F F F F
COUNT 1 1 1 1
WIDTH 3784
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 3784
DATA ascii
0.068493545 -0.18897545 -0.6662081 0.007968704
0.26833203 -0.18425867 -1.5039357 0.02365576
0.19286658 -0.2141684 -1.58289 0.038087178
0.070703566 -0.17931458 -0.69418937 0.016636848
0.044586033 -0.18726173 -0.6926071 0.024707714
0.04002113 -0.20350328 -0.68689686 0.018577512
0.029185327 -0.18594348 -0.73340106 0.12292312
0.0027626567 -0.20299685 -1.5578543 0.15424652
-0.031320766 -0.20478198 -0.70128816 0.13745676
-0.06351853 -0.20185146 -0.61755043 0.15234329
-0.08655308 -0.19128543 -0.6776818 0.170851
1.0159657 -0.41043654 -6.8713074 0.05946503
-0.031778865 -0.20536968 -1.5218562 0.15976532
-0.09223208 -0.19543779 -0.61643535 0.12331226
0.02384475 -0.20319816 -1.7497014 0.15273231
-0.10013421 -0.19931296 -0.5924832 0.16186734
0.49137634 -0.09052197 -5.7263794 0.16080469
To viaualize the point cloud you can use pcl_viewer or Matlab. In Matlab I just typed
ptCloud = pcread('pointCloud.pcd');
pcshow(ptCloud);
Related
I have created a simple Android-Application that takes a photo and stores the devices GPS infos in the exif-tags for the jpg-file. The following code shows this process (i know it's messy)
Android.Locations.Location loc = await client.GetLastLocationAsync();
ByteBuffer buffer = mImage.GetPlanes()[0].Buffer;
byte[] bytes = new byte[buffer.Remaining()];
buffer.Get(bytes);
using (var output = new FileOutputStream(mFile))
{
try
{
output.Write(bytes);
output.Flush();
ExifInterface exif = new ExifInterface(mFile.AbsolutePath);
string[] degMinSec = Location.Convert(loc.Latitude, Format.Seconds).Split(':');
string dms = degMinSec[0] + "/1," + degMinSec[1] + "/1" + degMinSec[2] + "/1000";
string[] degMinSec1 = Location.Convert(loc.Longitude, Format.Seconds).Split(':');
string dms1 = degMinSec1[0] + "/1," + degMinSec1[1] + "/1" + degMinSec1[2] + "/1000";
exif.SetAttribute(ExifInterface.TagGpsLatitude, dms);
exif.SetAttribute(ExifInterface.TagGpsLatitudeRef, loc.Latitude < 0?"S":"N");
exif.SetAttribute(ExifInterface.TagGpsLongitude, dms1);
exif.SetAttribute(ExifInterface.TagGpsLongitudeRef, loc.Longitude < 0 ? "W" : "E");
exif.SaveAttributes();
}
...
So now to the problem:
When i take a picture and debug the loc variable, it looks as this:
as you can see, the latitude is 48.4080605 and de longitude is 15.6257273
when i debug the converted values dms & dms1 they show these values:
dms represents latitude and has the value 48° 24' 29.0178'', dms1 represents longitude and has the value 15° 37' 32.61828''.
when i look at the pictures exif-data in metapicz.com it shows these values:
can anyone explain me what is going on and what i'm doing wrong?
i can't figure out why it shows a different location than it should
dms = degMinSec[0] + "/1," + degMinSec[1] + "/1" + degMinSec[2] + "/1000";
Should that not be
dms = degMinSec[0] + "/1," + degMinSec[1] + "/1," + degMinSec[2] + "/1000";
?
I'm using the code below to print a bitmap with the Android SDK which can be found at this link:
https://www.zebra.com/us/en/products/software/barcode-printers/link-os/link-os-sdk.html#mainpartabscontainer_794f=downloads
//variables
int printQty= 3;
String printerAddress= ...;
Connection connection = new BluetoothConnection(printerAddress);
connection.open();
//for removing the useless margin printed
connection.write("! U1 JOURNAL\r\n! U1 SETFF 100 2\r\n".getBytes());
ZebraPrinter printer = ZebraPrinterFactory.getInstance(connection);
Bitmap bitmapToPrint = large bitmap here;
ZebraImageAndroid zebraImageToPrint = new ZebraImageAndroid(bitmapToPrint);
for (int i = 0; i < printQty; i++){
printer.printImage(zebraImageToPrint, 0, 0, -1, -1, false);
}
bitmapToPrint.recycle();
connection.close();
The problem is:
the printing process is taking a lot of time because the bitmap is large.
Is there a way to avoid a loop and tell to the printer how many quantity to print without calling printImage multiple times?
i've searched a lot in the documentation but i've not found something usefull, is there a way to achieve this? With CPCL can i achieve the same effect?
Thanks
Mat
use storeimage to store the image on the printer. Then send pritner commands to print the image with a print quantitiy of three. It your printer is using zpl it would look something like "^xa^xgR:image.grf^fs^pq3^xz"
You will want to look at the ZPL guide to be sure but that is the general solution. Store the image and then recall it. In the end delete the image or just always use the same file name and the image will just write over the last image.
This how i solved it at the end
int printQty = 5; //or whatever number you want
Coonection connection = new BluetoothConnection(deviceAddress);
connection.open();
//with SETFF command we add 50 millimiters of margin at the end of the the print (without this the print is wasting a lot of paper)
//ref https://km.zebra.com/kb/index?page=forums&topic=021407fb4efb3012e55595f77007e8a
connection.write("! U1 setvar \"device.languages\" \"CPCL\"\r\n".getBytes());
connection.write("! U1 JOURNAL\r\n! U1 SETFF 50 2\r\n".getBytes());
ZebraPrinter printer = ZebraPrinterFactory.getInstance(PrinterLanguage.CPCL, connection);
//get the bitmap to print
bitmapToPrint = PdfUtils.pdfToBitmap(getApplicationContext(), pdfStamped, 0);
int width = bitmapToPrint.getWidth();
int height = bitmapToPrint.getHeight();
float aspectRatio = width / ZEBRA_RW420_WIDTH; //ZEBRA_RW420_WIDTH = 800f
float multiplier = 1 / aspectRatio;
//scale the bitmap to fit the ZEBRA_RW_420_WIDTH print
bitmapToPrint = Bitmap.createScaledBitmap(bitmapToPrint, (int)(width * multiplier), (int)(height * multiplier), false);
//get the new bitmap and add 20 pixel more of margin
int newBitmapHeight = bitmapToPrint.getHeight() + 20;
//create the Zebra object with the new Bitmap
ZebraImageAndroid zebraImageToPrint = new ZebraImageAndroid(bitmapToPrint);
//the image is sent to the printer and stored in R: folder
printer.storeImage("R:TEMP.PCX", zebraImageToPrint, -1, -1);
//create the print commands string
String printString =
"! 0 200 200 " + newBitmapHeight + " " + printQty + "\r\n"//set the height of the bitmap and the quantity to print
+ "PW 831" + "\r\n"//MAX_PRINT_WIDTH
+ "TONE 50" + "\r\n"//print intensity tone 0-200
+ "SPEED 2" + "\r\n"//print speed (less = more accurate) 1 2.5cm/s | 2 - 5cm/s | 3 - 7.6cm/s
+ "ON-FEED REPRINT" + "\r\n"//enable reprint on FEED button press
+ "NO-PACE" + "\r\n"
+ "BAR-SENSE" + "\r\n"
+ "PCX 20 20 !<TEMP.PCX" + "\r\n"//get the image we stored before in the printer
+ "FORM" + "\r\n"
+ "PRINT" + "\r\n";//print
//send the commands to the printer, the image will be printed now
connection.write(printString.getBytes());
//delete the image at the end to prevent printer memory sutaration
connection.write("! U1 do \"file.delete\" \"R:TEMP.PCX\"\r\n".getBytes());
//close the connection with the printer
connection.close();
//recycle the bitmap
bitmapToPrint.recycle();
I have Modified #MatPag answer and added support for multiple printers of zebra.
Follow these steps:
Turn Off Zebra printer
press feed + power button (release power button when power bars appear but release feed button only when printer prints something)
You will receive a print after sometime which have feild like this:
Label:
Width: 576 dots <------- this is width in px
Now Use Below Function to print out your zebra print without extra spaces:
private void printPhotoFromExternalManual(final Bitmap bitmapToPrint,final int printingQty, final int widthSupported) {
new Thread(new Runnable() {
public void run() {
try {
getAndSaveSettings();
Looper.prepare();
helper.showLoadingDialog("Sending image to printer");
Connection connection = getZebraPrinterConn();
int printQty = printingQty; //or whatever number you want
connection.open();
//with SETFF command we add 50 millimiters of margin at the end of the the print (without this the print is wasting a lot of paper)
//ref https://km.zebra.com/kb/index?page=forums&topic=021407fb4efb3012e55595f77007e8a
// connection.write("! U1 setvar \"device.languages\" \"CPCL\"\r\n".getBytes());
connection.write("! U1 JOURNAL\r\n! U1 SETFF 50 2\r\n".getBytes());
ZebraPrinter printer = ZebraPrinterFactory.getInstance(PrinterLanguage.CPCL, connection);
float ZEBRA_WIDTH = widthSupported;
int width = bitmapToPrint.getWidth();
int height = bitmapToPrint.getHeight();
float aspectRatio = width / ZEBRA_WIDTH; //ZEBRA_RW420_WIDTH = 800f
float multiplier = 1 / aspectRatio;
//scale the bitmap to fit the ZEBRA_RW_420_WIDTH print
Bitmap bitmapToPrint1 = Bitmap.createScaledBitmap(bitmapToPrint, (int) (width * multiplier), (int) (height * multiplier), false);
bitmapToPrint.recycle();
//get the new bitmap and add 20 pixel more of margin
int newBitmapHeight = bitmapToPrint1.getHeight() + 20;
//create the Zebra object with the new Bitmap
ZebraImageAndroid zebraImageToPrint = new ZebraImageAndroid(bitmapToPrint1);
//the image is sent to the printer and stored in R: folder
printer.storeImage("R:TEMP.PCX", zebraImageToPrint, -1, -1);
//create the print commands string
String printString =
"! 0 200 200 " + newBitmapHeight + " " + printQty + "\r\n"//set the height of the bitmap and the quantity to print
+ "PW " + ((int) ZEBRA_WIDTH) + "\r\n"//MAX_PRINT_WIDTH
+ "TONE 50" + "\r\n"//print intensity tone 0-200
+ "SPEED 2" + "\r\n"//print speed (less = more accurate) 1 2.5cm/s | 2 - 5cm/s | 3 - 7.6cm/s
+ "ON-FEED REPRINT" + "\r\n"//enable reprint on FEED button press
+ "NO-PACE" + "\r\n"
+ "BAR-SENSE" + "\r\n"
+ "PCX 20 20 !<TEMP.PCX" + "\r\n"//get the image we stored before in the printer
+ "FORM" + "\r\n"
+ "PRINT" + "\r\n";//print
//send the commands to the printer, the image will be printed now
connection.write(printString.getBytes());
//delete the image at the end to prevent printer memory sutaration
connection.write(("! U1 do \"file.delete\" \"R:TEMP.PCX\"\r\n").getBytes());
//close the connection with the printer
connection.close();
//recycle the bitmap
bitmapToPrint1.recycle();
if (file != null) {
file.delete();
file = null;
}
} catch (ConnectionException e) {
helper.showErrorDialogOnGuiThread(e.getMessage());
} catch (ZebraIllegalArgumentException e) {
helper.showErrorDialogOnGuiThread(e.getMessage());
} finally {
helper.dismissLoadingDialog();
Looper.myLooper().quit();
}
}
}).start();
}
Above function is used like this in my case: printPhotoFromExternalManual(bitmap,1,576);
Enjoy happing coding
I am currently saving values to a text file in my application. The values are read from an EEG headset every second and are then stored within the text file.
The values are read using a handler e.g.:
final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// msg.what determines the type of each message
switch (msg.what) {
case TGDevice.MSG_EEG_POWER:
eegPower = (TGEegPower) msg.obj;
//trace code
Log.d("LSD", "highAlpha: " + eegPower.highAlpha);
Log.d("LSD", "lowAlpha: " + eegPower.lowAlpha);
Log.d("LSD", "highBeta: " + eegPower.highBeta);
Log.d("LSD", "lowBeta: " + eegPower.lowBeta);
Log.d("LSD", "lowGamma: " + eegPower.lowGamma);
Log.d("LSD", "midGamma: " + eegPower.midGamma);
Log.d("LSD", "delta: " + eegPower.delta);
Log.d("LSD", "theta: " + eegPower.theta);
//adding all the EEGpowers to an arraylist to help add them to file
ArrayList<String> EEGPowers= new ArrayList<String>();
EEGPowers.add("highAlpha: " + eegPower.highAlpha);
EEGPowers.add("lowAlpha: " + eegPower.lowAlpha);
EEGPowers.add("highBeta: " + eegPower.highBeta);
EEGPowers.add("lowBeta: " + eegPower.lowBeta);
EEGPowers.add("lowGamma: " + eegPower.lowGamma);
EEGPowers.add("midGamma: " + eegPower.midGamma);
EEGPowers.add("delta: " + eegPower.delta);
EEGPowers.add("theta: " + eegPower.theta);
for(String s: EEGPowers){
writeToFileEEGPower(s);
}
//rest of handler...
The following method is the method used to save the values to file:
public void writeToFileEEGPower(String data){
//creating time for the file
Time t= new Time();
int timeFileSecond= t.second;
int timeFileDate= t.yearDay;
int timeFileYear= t.year;
//creating file name
String fileName= "MathsGame" + timeFileSecond + timeFileDate + timeFileYear + android.os.Build.SERIAL;
//creating the file where the contents will be written to
File file= new File(dir, fileName + ".txt");
FileOutputStream os;
try{
boolean append= true;
os= new FileOutputStream(file, append);
String writeMe =data + "\n";
os.write(writeMe.getBytes());
os.close();
} catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
The method and handler work as is, however my issue is that the values are not formatted as I would like when they are saved and are very messy as you can see:
E.g. of current text file:
I would like my text file to be formatted like this:
How can I implement this formatting in my code?
EDIT (Attempt at formatting):
//Declared globally outside handler
final int maxWordLength = 15;
String spaces[] = new String[maxWordLength];
//Within handler:
//setting up the array of maxlength etc
spaces[0] = "";
for(int i=1; i<maxWordLength ;i++){
spaces[i] = spaces[i-1]+" ";
}
int seconds=0;
//CREATING THE HEADER IN THE TEXT FILE
writeToFileEEGPower(order("Seconds")+order("highAlpha")+order("lowAlpha")+order("highBeta")+order("LowBeta")+
order("lowGamma")+order("midGamma")+order("Delta")+order("Theta")+ "\n");
//creating the string to be written to file
String line = order(seconds+"")+order(eegPower.highAlpha+"")+order(eegPower.lowAlpha+"")+order(eegPower.highBeta+"")+
order(eegPower.lowBeta+"")+order(eegPower.midGamma+"")+order(eegPower.delta+"")+order(eegPower.theta+"")+ "\n";
//write the string to file
writeToFileEEGPower(line);
Current sample output in text file:
You can define your max 'word' length, and complete every 'word' with empty spaces.
for example:
STEP 1
Define maxWordLength. this value describe the width of each column. Should this value will be slightly larger than the longest word (In this example length of 'highAlpha:'=10, choose number>10).
final int maxWordLength = 15;
STEP 2
Create array of empty spaces.
String spaces[] = {""," "," "," "," ", /*....*/ " "};// Complete the missing words up to the last word with 15 spaces.
Or create it dynamically:
String spaces[] = new String[maxWordLength];
spaces[0] = "";
for(int i=1; i<maxWordLength ;i++){
spaces[i] = spaces[i-1]+" ";
}
STEP 3
Define the 'Seconds' var, create the order function at your class and write the header row to the file:
int seconds=0;
//table header row
writeToFileEEGPower(order("Seconds")+order("highAlpha")+order("lowAlpha")+order("highBeta")/+.../);
private String order(String value){
return (value + spaces[maxWordLength-value.length()]);
}
STEP 4
For each handleMessage create a line and save it to the file:
String line = order(seconds+"")+order(eegPower.highAlpha+"")+order(eegPower.lowAlpha+"")+order(eegPower.highBeta+"")//+...;
writeToFileEEGPower(line);
I'm following javacv Face Detection/Recognition code, there is confusion regarding face recognition.. What I'm doing is (Sorry if it sounds stupid but I'm stuck)
1) Detect Face crop it and save it to sdcard and place path in learn.txt file (Learning part)
2) Detect Face crop it and find it in existing faces whether it exists or not, but it always return nearest position even if the face doesn't exist in sample faces..
what I'm doing wrong?
// Method, I'm using to recognize face
public Integer recognizeFace(Bitmap face, Context context) {
Log.i(TAG, "===========================================");
Log.i(TAG, "recognizeFace (single face)");
float[] projectedTestFace;
float confidence = 0.0f;
int nearest = -1; // closest match -- -1 for nothing.
int iNearest;
if (trainPersonNumMat == null) {
return null;
}
Log.i(TAG, "NUMBER OF EIGENS: " + nEigens);
// project the test images onto the PCA subspace
projectedTestFace = new float[nEigens];
// Start timing recognition
long startTime = System.nanoTime();
testFaceImg = bmpToIpl(face);
// saveBmp(face, "blah");
// convert Bitmap it IplImage
//testFaceImg = IplImage.create(face.getWidth(), face.getHeight(),
// IPL_DEPTH_8U, 4);
//face.copyPixelsToBuffer(testFaceImg.getByteBuffer());
// project the test image onto the PCA subspace
cvEigenDecomposite(testFaceImg, // obj
nEigens, // nEigObjs
new PointerPointer(eigenVectArr), // eigInput (Pointer)
0, // ioFlags
null, // userData
pAvgTrainImg, // avg
projectedTestFace); // coeffs
// LOGGER.info("projectedTestFace\n" +
// floatArrayToString(projectedTestFace));
Log.i(TAG, "projectedTestFace\n" + floatArrayToString(projectedTestFace));
final FloatPointer pConfidence = new FloatPointer(confidence);
iNearest = findNearestNeighbor(projectedTestFace, new FloatPointer(pConfidence));
confidence = pConfidence.get();
// truth = personNumTruthMat.data_i().get(i);
nearest = trainPersonNumMat.data_i().get(iNearest); // result
// get endtime and calculate time recognition process takes
long endTime = System.nanoTime();
long duration = endTime - startTime;
double seconds = (double) duration / 1000000000.0;
Log.i(TAG, "recognition took: " + String.valueOf(seconds));
Log.i(TAG, "nearest = " + nearest + ". Confidence = " + confidence);
Toast.makeText(context, "Nearest: "+nearest+" Confidence: "+confidence, Toast.LENGTH_LONG).show();
//Save the IplImage so we can see what it looks like
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "/sdcard/saved_images/" + nearest + " " + String.valueOf(seconds) + " " + String.valueOf(confidence) + " " + n + ".jpg";
Log.i(TAG, "Saving image as: " + fname);
cvSaveImage(fname, testFaceImg);
return nearest;
} // end of recognizeFace
EDIT The confidence is always negative!
Thanks in advance
I have this code..
String you = buf.readLine();
Log.d("STRING", ikaw);
StringTokenizer st = new StringTokenizer(you);
double lat = Double.parseDouble(st.nextToken());
double lng = Double.parseDouble(st.nextToken());
int type = Integer.parseInt(st.nextToken());
String text = st.nextToken();
Log.d("File Reading stuff", "success = " + lat);
Log.d("File Reading stuff", "success = " + lng);
Log.d("File Reading stuff", "success = " + type);
Log.d("File Reading stuff", "success = " + text);
How am i suppose to test if it is already the end of file?
I don't know how many lines there are in my file and I need to print all of them.
I know i should place my code inside a while loop, but I have no idea how to get the end of file.
I assume the code you have listed is inside a loop, and I assume buf is an instance of BufferedReader. You just need to check for null after you call readLine(). It returns null when you've hit the end of the file.