Fix/optimize Android put/get functions

pull/19503/head
Giles Payne 4 years ago
parent fba70f7991
commit 5cf08b0722
  1. 21
      modules/core/misc/java/test/MatTest.java
  2. 173
      modules/java/generator/src/cpp/Mat.cpp
  3. 16
      modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java
  4. 15
      modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java

@ -455,6 +455,27 @@ public class MatTest extends OpenCVTestCase {
bytesNum = sm.get(1, 1, buff11);
assertEquals(4, bytesNum);
assertTrue(Arrays.equals(new short[] {340, 341, 0, 0}, buff11));
Mat m2 = new Mat(new int[]{ 5, 6, 8 }, CvType.CV_16S);
short[] data = new short[(int)m2.total()];
for (int i = 0; i < data.length; i++ ) {
data[i] = (short)i;
}
m2.put(new int[] {0, 0, 0}, data);
Mat matNonContinuous = m2.submat(new Range[]{new Range(1,4), new Range(2,5), new Range(3,6)});
Mat matContinuous = matNonContinuous.clone();
short[] outNonContinuous = new short[(int)matNonContinuous.total()];
matNonContinuous.get(new int[] { 0, 0, 0 }, outNonContinuous);
short[] outContinuous = new short[(int)matNonContinuous.total()];
matContinuous.get(new int[] { 0, 0, 0 }, outContinuous);
assertArrayEquals(outNonContinuous, outContinuous);
Mat subMat2 = m2.submat(new Range[]{new Range(1,4), new Range(1,5), new Range(0,8)});
Mat subMatClone2 = subMat2.clone();
short[] outNonContinuous2 = new short[(int)subMat2.total()];
subMat2.get(new int[] { 0, 1, 1 }, outNonContinuous2);
short[] outContinuous2 = new short[(int)subMat2.total()];
subMatClone2.get(new int[] { 0, 1, 1 }, outContinuous2);
assertArrayEquals(outNonContinuous2, outContinuous2);
}
public void testGetNativeObjAddr() {

@ -2129,80 +2129,83 @@ namespace {
#undef JOCvT
}
template<typename T> static int mat_put(cv::Mat* m, int row, int col, int count, int offset, char* buff)
{
if(! m) return 0;
if(! buff) return 0;
count *= sizeof(T);
int rest = ((m->rows - row) * m->cols - col) * (int)m->elemSize();
if(count>rest) count = rest;
int res = count;
static size_t idx2Offset(cv::Mat* mat, std::vector<int>& indices) {
size_t offset = indices[0];
for (int dim=1; dim < mat->dims; dim++) {
offset = offset*mat->size[dim] + indices[dim];
}
return offset;
}
if( m->isContinuous() )
{
memcpy(m->ptr(row, col), buff + offset, count);
} else {
// row by row
int num = (m->cols - col) * (int)m->elemSize(); // 1st partial row
if(count<num) num = count;
uchar* data = m->ptr(row++, col);
while(count>0){
memcpy(data, buff + offset, num);
count -= num;
buff += num;
num = m->cols * (int)m->elemSize();
if(count<num) num = count;
data = m->ptr(row++, 0);
}
static void offset2Idx(cv::Mat* mat, size_t offset, std::vector<int>& indices) {
for (int dim=mat->dims-1; dim>=0; dim--) {
indices[dim] = offset % mat->size[dim];
offset = (offset - indices[dim]) / mat->size[dim];
}
return res;
}
// returns true if final index was reached
static bool updateIdx(cv::Mat* m, std::vector<int>& idx, int inc) {
for (int i=m->dims-1; i>=0; i--) {
if (inc == 0) return false;
idx[i] = (idx[i] + 1) % m->size[i];
inc--;
}
return true;
static bool updateIdx(cv::Mat* mat, std::vector<int>& indices, size_t inc) {
size_t currentOffset = idx2Offset(mat, indices);
size_t newOffset = currentOffset + inc;
bool reachedEnd = newOffset>=(size_t)mat->total();
offset2Idx(mat, reachedEnd?0:newOffset, indices);
return reachedEnd;
}
template<typename T> static int mat_put_idx(cv::Mat* m, std::vector<int>& idx, int count, int offset, char* buff)
{
template<typename T> static int mat_copy_data(cv::Mat* m, std::vector<int>& idx, int count, char* buff, bool isPut) {
if(! m) return 0;
if(! buff) return 0;
count *= sizeof(T);
int rest = (int)m->elemSize();
for (int i = 0; i < m->dims; i++) {
rest *= (m->size[i] - idx[i]);
}
if(count>rest) count = rest;
int res = count;
size_t countBytes = count * sizeof(T);
size_t remainingBytes = (size_t)(m->total() - idx2Offset(m, idx))*m->elemSize();
countBytes = (countBytes>remainingBytes)?remainingBytes:countBytes;
int res = (int)countBytes;
if( m->isContinuous() )
{
memcpy(m->ptr(idx.data()), buff + offset, count);
if (isPut) {
memcpy(m->ptr(idx.data()), buff, countBytes);
} else {
memcpy(buff, m->ptr(idx.data()), countBytes);
}
} else {
// dim by dim
int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
if(count<num) num = count;
size_t blockSize = m->size[m->dims-1] * m->elemSize();
size_t firstPartialBlockSize = (m->size[m->dims-1] - idx[m->dims-1]) * m->step[m->dims-1];;
for (int dim=m->dims-2; dim>=0 && blockSize == m->step[dim]; dim--) {
blockSize *= m->size[dim];
firstPartialBlockSize += (m->size[dim] - (idx[dim]+1)) * m->step[dim];
}
size_t copyCount = (countBytes<firstPartialBlockSize)?countBytes:firstPartialBlockSize;
uchar* data = m->ptr(idx.data());
while(count>0){
memcpy(data, buff + offset, num);
updateIdx(m, idx, num / (int)m->elemSize());
count -= num;
buff += num;
num = m->size[m->dims-1] * (int)m->elemSize();
if(count<num) num = count;
while(countBytes>0){
if (isPut) {
memcpy(data, buff, copyCount);
} else {
memcpy(buff, data, copyCount);
}
updateIdx(m, idx, copyCount / m->elemSize());
countBytes -= copyCount;
buff += copyCount;
copyCount = countBytes<blockSize?countBytes:blockSize;
data = m->ptr(idx.data());
}
}
return res;
}
template<typename T> static int mat_put_idx(cv::Mat* m, std::vector<int>& idx, int count, int offset, char* buff)
{
return mat_copy_data<T>(m, idx, count, buff + offset, true);
}
template<typename T> static int mat_put(cv::Mat* m, int row, int col, int count, int offset, char* buff)
{
int indicesArray[] = { row, col };
std::vector<int> indices(indicesArray, indicesArray+2);
return mat_put_idx<T>(m, indices, count, offset, buff);
}
template<class ARRAY> static jint java_mat_put(JNIEnv* env, jlong self, jint row, jint col, jint count, jint offset, ARRAY vals)
{
static const char *method_name = JavaOpenCVTrait<ARRAY>::put;
@ -2455,68 +2458,16 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx
} // extern "C"
template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
template<typename T> static int mat_get_idx(cv::Mat* m, std::vector<int>& idx, int count, char* buff)
{
if(! m) return 0;
if(! buff) return 0;
int bytesToCopy = count * sizeof(T);
int bytesRestInMat = ((m->rows - row) * m->cols - col) * (int)m->elemSize();
if(bytesToCopy > bytesRestInMat) bytesToCopy = bytesRestInMat;
int res = bytesToCopy;
if( m->isContinuous() )
{
memcpy(buff, m->ptr(row, col), bytesToCopy);
} else {
// row by row
int bytesInRow = (m->cols - col) * (int)m->elemSize(); // 1st partial row
while(bytesToCopy > 0)
{
int len = std::min(bytesToCopy, bytesInRow);
memcpy(buff, m->ptr(row, col), len);
bytesToCopy -= len;
buff += len;
row++;
col = 0;
bytesInRow = m->cols * (int)m->elemSize();
}
}
return res;
return mat_copy_data<T>(m, idx, count, buff, false);
}
template<typename T> static int mat_get_idx(cv::Mat* m, std::vector<int>& idx, int count, char* buff)
template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
{
if(! m) return 0;
if(! buff) return 0;
count *= sizeof(T);
int rest = (int)m->elemSize();
for (int i = 0; i < m->dims; i++) {
rest *= (m->size[i] - idx[i]);
}
if(count>rest) count = rest;
int res = count;
if( m->isContinuous() )
{
memcpy(buff, m->ptr(idx.data()), count);
} else {
// dim by dim
int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
if(count<num) num = count;
uchar* data = m->ptr(idx.data());
while(count>0){
memcpy(buff, data, num);
updateIdx(m, idx, num / (int)m->elemSize());
count -= num;
buff += num;
num = m->size[m->dims-1] * (int)m->elemSize();
if(count<num) num = count;
data = m->ptr(idx.data());
}
}
return res;
int indicesArray[] = { row, col };
std::vector<int> indices(indicesArray, indicesArray+2);
return mat_get_idx<T>(m, indices, count, buff);
}
template<class ARRAY> static jint java_mat_get(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) {

@ -279,19 +279,23 @@ public class OpenCVTestCase extends TestCase {
}
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
if (ar1.length != ar2.length) {
fail("Arrays have different sizes.");
}
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertArrayEquals(short[] ar1, short[] ar2) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i]);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
if (ar1.length != ar2.length) {
fail("Arrays have different sizes.");
}
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i], epsilon);

@ -305,19 +305,22 @@ public class OpenCVTestCase extends TestCase {
}
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
if (ar1.length != ar2.length) {
fail("Arrays have different sizes.");
}
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
}
public static void assertArrayEquals(short[] ar1, short[] ar2) {
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i]);
}
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
if (ar1.length != ar2.length) {
fail("Arrays have different sizes.");
}
assertEquals(ar1.length, ar2.length);
for (int i = 0; i < ar1.length; i++)
assertEquals(ar1[i], ar2[i], epsilon);

Loading…
Cancel
Save