Ask Your Question
0

confused on Mat put

asked 2017-08-09 23:01:09 -0600

yyliu gravatar image

updated 2017-08-10 00:29:17 -0600

berak gravatar image

I'm a newer on java opencv, now i have a few confusion on Mat put functions.

The confusion is: the behavior of Mat.put(int ,int, double ...) and Mat.put(int, int, float[]) are different ( the 2 functions are in org.opencv.core.Mat.java line 2493 and line 2504). So i tried to look why by viewing source code and i found the native code are located in opencv-2.4.7/modules/java/generator/src/cpp/Mat.cpp

nPutF for put(int, int, float[])'s code:

   1931 JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutF
   1932     (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jfloatArray vals);
   1933 
   1934 JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutF
   1935     (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jfloatArray vals)
   1936 {
   1937     static const char method_name[] = "Mat::nPutF()";
   1938     try {
   1939         LOGD("%s", method_name);
   1940         cv::Mat* me = (cv::Mat*) self;
   1941         if(! self) return 0; // no native object behind
   1942         if(me->depth() != CV_32F) return 0; // incompatible type
   1943         if(me->rows<=row || me->cols<=col) return 0; // indexes out of range
   1944 
   1945         char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0);
   1946         int res = mat_put<float>(me, row, col, count, values);
   1947         env->ReleasePrimitiveArrayCritical(vals, values, 0);
   1948         return res;
   1949     } catch(const std::exception &e) {
   1950         throwJavaException(env, &e, method_name);
   1951     } catch (...) {
   1952         throwJavaException(env, 0, method_name);
   1953     }
   1954 
   1955     return 0;
   1956 }

----------and here is mat_put

   1817 template<typename T> static int mat_put(cv::Mat* m, int row, int col, int count, char* buff)
   1818 {
   1819     if(! m) return 0;
   1820     if(! buff) return 0;
   1821 
   1822     count *= sizeof(T);
   1823     int rest = ((m->rows - row) * m->cols - col) * (int)m->elemSize();
   1824     if(count>rest) count = rest;
   1825     int res = count;
   1826 
   1827     if( m->isContinuous() )
   1828     {
   1829         memcpy(m->ptr(row, col), buff, count);
   1830     } else {
   1831         // row by row
   1832         int num = (m->cols - col) * (int)m->elemSize(); // 1st partial row
   1833         if(count<num) num = count;
   1834         uchar* data = m->ptr(row++, col);
   1835         while(count>0){
   1836             memcpy(data, buff, num);
   1837             **count -= num;**
   1838             buff += num;
   1839             num = m->cols * (int)m->elemSize();
   1840             if(count<num) num = count;
   1841             data = m->ptr(row++, 0);
   1842         }
   1843     }
   1844     return res;
   1845 }

but nPutD for put(int, int, double ...):

   1757 JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutD
   1758     (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jdoubleArray vals);
   1759 
   1760 JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutD
   1761     (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jdoubleArray vals)
   1762 {
   1763     static const char method_name[] = "Mat::nPutD()";
   1764     try {
   1765         LOGD("%s", method_name);
   1766         cv::Mat* me = (cv::Mat*) self;
   1767         if(!me || !me->data) return 0;  // no native object behind
   1768         if(me->rows<=row || me->cols<=col) return 0; // indexes out of range
   1769 
   1770         int rest = ((me->rows - row) * me->cols - col) * me->channels();
   1771         if(count>rest) count = rest;
   1772         int res = count;
   1773         double* values = (double*)env->GetPrimitiveArrayCritical(vals, 0);
   1774 ...
(more)
edit retag flag offensive close merge delete

Comments

You might expect the behavior of the Mat::put() function to be the same whether the input data is a float or double array except for any possible casting of the input type to the output type. Indeed I found this reference for the macro (function) PUT_ITEM you list above. It has a comment that mentions just this point about how double is treated differently.

// unlike other nPut()-s this one (with double[]) should convert input values to correct type 
 2094 #define PUT_ITEM(T, R, C) { T*dst = (T*)me->ptr(R, C); for(int ch=0; ch<me->channels() && count>0; count--,ch++,src++,dst++) *dst = cv::saturate_cast<T>(*src); }

Here is the line... Mat code on github

jetkaczyk gravatar imagejetkaczyk ( 2018-02-18 17:24:23 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-02-18 17:54:31 -0600

jetkaczyk gravatar image

It appears that the double version of Mat::put() you list above allows for casting of the double type data into other types. That would be the root of the difference. In either case, float or double the goal is to write the input data into the output memory locations corresponding to the Mat starting at cell=(row,col).

For the double case, the write operation is performed cell-by-cell with the macro PUT_ITEM() and the consecutive memory locations don't have to be part of a continuous block of memory. This is also where the casting between types is performed. The variable count is converted to the number of bytes that need to be written. There are checks that this count is not larger than the allocated memory. After that there is no need to check it when writing count_number of cells.

For the float case, the memcpy() function is used either for a continuous block of memory or row-by-row. In the row-by-row case, you need to check that the available memory for just that row is sufficient to save the input data for one row. At the very end row, you also need to make sure the remaining input data is going to fill a whole row. So the counting and checking is a little more involved.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2017-08-09 23:01:09 -0600

Seen: 1,598 times

Last updated: Feb 18 '18