I've wrote simple template-matching program using OpenCV, which produces surprisingly different results on Android and OSx.
First, see what I'm doing:
IplImage *image = cvLoadImage("test3a.png", -1);
Mat templateMat(image);
// detecting keypoints
OrbFeatureDetector detector(500);
std::vector<KeyPoint> templateKeypoints;
detector.detect(templateMat, templateKeypoints);
// computing descriptors
Mat templateDescriptors;
OrbDescriptorExtractor extractor;
extractor.compute(templateMat, templateKeypoints, templateDescriptors);
// matches
BFMatcher matcher(cv::NORM_HAMMING2);
std::vector<std::vector<DMatch> > matches;
matcher.knnMatch(templateDescriptors, templateDescriptors, matches, 2);
Now next see what I'm getting:
Running same snippet on Nexus i9250 running Android 4.2.2 and on OSx 10.7(Lion) give these results:
Mat Objects: Same on both OSes
Keypoints: [On Android][2], [On OSx][3], [DIFFERENCE][4]
Descriptors: [On Android][5], [On OSx][6], [DIFFERENCE][7]
Matches: [On Android][8], [On OSx][9], [DIFFERENCE][10]
NOTE:
There is no difference, if I sort these files; So what I'm not getting is, why I'm getting different ordered results??
Geting them in order is my requirement, as I need such for further computations.
Further, running same code-snippet on same platform always produces same ordered results.
Stackexchange limits my account to post more than 2 links in post, so please check comments for the links.
Related
I upgraded my Samsung Galaxy S4 from latest KitKat to Lollipop (5.0.1) yesterday and my IR remote control app that I have used for months stopped working.
Since I was using a late copy of KitKat ConsumerIrManager, the transmit( ) function was sending the number of pulses using the code below. It worked very nicely.
private void irSend(int freqHz, int[] pulseTrainInMicroS) {
int [] pulseCounts = new int [pulseTrainInMicroS.length];
for (int i=0; i<pulseTrainInMicroS.length; i++) {
long iValue = pulseTrainInMicroS[i] * freqHz / 1000000;
pulseCounts[i] = (int) iValue;
}
m_IRService.transmit(freqHz, pulseCounts);
}
when it stopped working yesterday, I began looking closely at it.
I noticed that the transmitted waveform is not having any relationship with the requested pulse train. even the code below doesn't work correctly! there is
private void TestSend() {
int [] pulseCounts = {100, 100, 100};
m_IRService.transmit(38000, pulseCounts);
}
the resulting waveforms had many problems and so are entirely useless.
the waveforms were entirely wrong
the frequency was wrong and the pulse spacing was not regular
they were not repeatable
looking at the demodulated waveform:
if my 100, 100, 100 were correctly rendered, I should have seen two pulses 2.6ms (before 4.4.3(?) 100 us) long. instead I received (see attached) "[demodulated] not repeatable 1.BMP" and "[demodulated] not repeatable 2.BMP". note that the waveform isn't 2 pulses...in fact, it's not even repeatable.
as for the captures below, the signal goes low when the IR is detected.
we should have seen two pulses going low for 2.6 ms and 2.6 ms between them (see green line below).
I had also tried shorter pulses using 50, 50, 50 and have observed that the first pulse isn't correct either (see below).
looking at the modulated waveform:
the frequency was not correct; instead, it was about 18kHz and irregular.
I'm quite experienced with this and have formal education in electronics.
It seems to me there's a bug in ConsumerIrManager.transmit( )...
curiously, the "WatchOn" application that comes with the phone still works.
thank you for any insights you can give.
Test equipment:
Tektronix TDS-2014B, 100 MHz, used in peak-detect mode.
As #IvanTellez says, a change was made in Android in respect to this functionality. Strangely, when I had it outputting simple IR signals (for troubleshooting purposes), the function behaves as shown above (erratically, wrong carrier frequency, etc). When I eventually returned to normal types of IR signals, it worked correctly.
I am trying to obtain a bitmap of the number of cores which are online in an android device. I am trying to create a command line tool in C++ that does some additional functionality based on how many cores are on and in particular which cores are available.
I have tried to use the following to try and get the number of cores on in C++:
cpus = sysconf( _SC_NPROCESSORS_ONLN );
This gives me the number of cores in the system but not which cores are presently ON.
Does anyone know a potential way to do this?
There's no clear cut answer to this problem.
You can use nproc to see how many cores you have available, but this won't tell you how many cores you have online.
You can use top to view the utilization of each core. You can then parse the information from top to infer which cores are presently on.
I was able to get the core online status using this:
int numCPU = 1;
char *status = (char*)calloc(32,sizeof(char));
char *directory = (char*)calloc(1024,sizeof(char));
sprintf(directory, "/sys/devices/system/cpu/cpu%d/online", numCPU);
FILE *online = fopen(directory, "r");
if(online)
{
size = fread(status, sizeof(char), 32, online);
}
printf("Core %d status=%d", numCPU, status);
i am trying to capture video on android using v4l2 under jni. i found some guide and followed the step:
fd = open("/dev/video0", O_RDWR);
/* init part */
ioctl(fd, VIDIOC_QUERYCAP, &caps);
ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc);
ioctl(fd, VIDIOC_S_FMT, &fmt);
ioctl(fd, VIDIOC_REQBUFS, &req);
ioctl(fd, VIDIOC_QUERYBUF, &buf);
ioctl(fd, VIDIOC_QBUF, &buf);
/* capture part */
FILE *fp = fopen("/sdcard/img.yuv", "wb");
for (i = 0; i < 20; i++)
{
ioctl(fd, VIDIOC_DQBUF, &buf);
fwrite(buffers[buf.index].start, 1, buf.bytesused, fp);
ioctl(fd, VIDIOC_QBUF, &buf);
}
fclose(fp);
this is the main structure of my code. all the function run correctly and return 0. however, when i open the output file with binary viewer, i found that all the data is 0.
is there any problem with my code? i got confused because all the functions returned 0.
Thanks!!
You are using an array called buffers[]. But I can't see where it's declared or what it stands for. If there is no code missing above, you will always get zeros cause you are writing buffer[] to the file and not the stuff you get from v4l2.
Further more, the initial values of caps, fmtdesc, fmt, req and buf prior to the ioctl command would be interesting too. Depending on their inital values, you will have different communication interfaces. Issues could be hidden in these parts.
As you wrote in your question, all ioctl commands would return 0, there should be no error. If everything behaves as expected. Another way to check for issues is calling
perror("<your comment or hint to line above>");
after each ioctl command. This would print you more information about errors on your std-out. ( more details about perror can be found in this thread When should I use perror("...") and fprintf(stderr, "...")?)
Are you trying to get the images from the camera? (on some phones video0 you used above is the back cam) On some android devices the camera has to be started by complex procedure using other device drivers besides videoXY. And trying to get the images from video0 while the official camera app is running might be difficult. The official v4l2 api says:
V4L2 drivers should not support multiple applications reading or writing the same data stream on a device by copying buffers, time multiplexing or similar means. This is better handled by a proxy application in user space.
From: http://linuxtv.org/downloads/v4l-dvb-apis/common.html#idp18553208
Can you post more (detailed) code? I might be able to help, as I'm doing very similar stuff.
To be able to reproduce it, it would be very interesting with which android device you are working (type / model number / android version).
I was looking at strcpy.S file in android platform at path libc/arch-arm/bionic, in this file there are many arm instructions which i am not able to understand, i am also referring ARM System Developers Guide.
Here except "tst" and "tstne" i am not able to find any refrence for others in any book or ARM refrence manual.
tst r2, #0xff00
iteet ne
strneh r2, [ip], #2
lsreq r2, r2, #8
r2, [ip]
tstne r2, #0xff
Not only these instructions there are many others in different files also.
Does anyone have any idea what these instructions are ?
The first instructions it the it-instruction from the thumb instructions set.
iteet ne
This instruction marks the next three instructions to be conditional executable. The last three characters of the instruction make a pattern consisting of e (else) or t (then). The operand 'ne' specifies the condition to be evaluated.
The other three instructions are ordinary ARM instructions with conditionals:
strneh r2, [ip], #2 ; store halfword if not equal
lsreq r2, r2, #8 ; logical shift right if equal
tstne r2, #0xff ; test if not equal
These are the three instructions affected by the it-instruction. They come with ne/eq conditional flags as well.
As you can see the conditions of the it-instructions and the conditions of the other three instructions are in conflict to each other. This is a bug in the code. Most likely it hasn't been discovered before because the code-snippet is from the ARM-big-endian code, and I know of no android phone that uses ARM in big endian.
Btw, it's worthwhile to know why the conditions are given in the it-instruction and in the instructions itself. This is part of the unified arm assembly standard. On the ARM you have two modes of operation: Thumb mode (uses It-instruction, less powerful) and ARM-mode (more powerful, uses condition-flags in the instructions itself).
If you limit yourself to the capabilities of the thumb-mode it is possible to write code that would compile in thumb and ARM-mode. This is done here.
If you assemble for Thumb-mode the It-instruction will be used to control the conditions of the next three instruction, and the conditions within the instructions gets ignored. If you assemble to ARM-instruction set the It-instruction gets ignored and the conditions from the instruction itself will become active.
This works well as long as the it-instruction and the conditions in the arm-instructions match. As I said before this is not the case here, so it will either not work in thumb-mode, arm-mode or both :-)
strneh is a store command with some conditional execution/size specifier suffixes. The ARM docs are a good place to start: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0068b/Chdehgih.html
If you google "arm conditional execution", you'll find a number of blogs/articles that may also help: http://blogs.arm.com/software-enablement/258-condition-codes-2-conditional-execution/
As for your *strneh" instruction:
str = store
ne = execute if not equal (Z flag clear)
h = perform a half-word operation
We ( http://www.mosync.com ) have compiled our ARM recompiler with the Android NDK which takes our internal byte code and generates ARM machine code. When executing recompiled code we see an enormous increase in performance, with one small exception, we can't use any Java Bitmap operations.
The native system uses a function which takes care of all the calls to the Java side which the recompiled code is calling. On the Java (Dalvik) side we then have bindings to Android features. There are no problems while recompiling the code or when executing the machine code. The exact same source code works on Symbian and Windows Mobile 6.x so the recompiler seems to generate correct ARM machine code.
Like I said, the problem we have is that we can't use Java Bitmap objects. We have verified that the parameters which are sent from the Java code is correct, and we have tried following the execution down in Android's own JNI systems. The problem is that we get an UnsupportedOperationException with "size must fit in 32 bits.". The problem seems consistent on Android 1.5 to 2.3. We haven't tried the recompiler on any Android 3 devices.
Is this a bug which other people have encountered, I guess other developers have done similar things.
I found the message in dalvik_system_VMRuntime.c:
/*
* public native boolean trackExternalAllocation(long size)
*
* Asks the VM if <size> bytes can be allocated in an external heap.
* This information may be used to limit the amount of memory available
* to Dalvik threads. Returns false if the VM would rather that the caller
* did not allocate that much memory. If the call returns false, the VM
* will not update its internal counts.
*/
static void Dalvik_dalvik_system_VMRuntime_trackExternalAllocation(
const u4* args, JValue* pResult)
{
s8 longSize = GET_ARG_LONG(args, 1);
/* Fit in 32 bits. */
if (longSize < 0) {
dvmThrowException("Ljava/lang/IllegalArgumentException;",
"size must be positive");
RETURN_VOID();
} else if (longSize > INT_MAX) {
dvmThrowException("Ljava/lang/UnsupportedOperationException;",
"size must fit in 32 bits");
RETURN_VOID();
}
RETURN_BOOLEAN(dvmTrackExternalAllocation((size_t)longSize));
}
This method is called, for example, from GraphicsJNI::setJavaPixelRef:
size_t size = size64.get32();
jlong jsize = size; // the VM wants longs for the size
if (reportSizeToVM) {
// SkDebugf("-------------- inform VM we've allocated %d bytes\n", size);
bool r = env->CallBooleanMethod(gVMRuntime_singleton,
gVMRuntime_trackExternalAllocationMethodID,
jsize);
I would say it seems that the code you're calling is trying to allocate a too big size. If you show the actual Java call which fails and values of all the arguments that you pass to it, it might be easier to find the reason.
I managed to find a work-around. When I wrap all the Bitmap.createBitmap calls inside a Activity.runOnUiThread() It works.