سؤال

I am currently converting some OpenCV code from C++ to Java. I can't use JavaCV, as we need the conversion in native Java, not a JNA. At one point in the code, I get the following assignment:

dst[x] = (uchar)(-(kHit >= kForeground));

Where dst is uchar*, kHit and kForeground are ints.

I've been unable to find anything about how this works, and Java will not recognize it as an operation. There is an operation on these two variables at another point in the code, and it stores one of two values: 255 or 0.

The code in question comes from opencv/video/src/bgfg_gaussmix.cpp.

هل كانت مفيدة؟

المحلول

In C++ a boolean expression produces one of two values - 0 or 1. When you apply the unary minus - to the result, you get 0 or -1. When you re-interpret -1 as uchar, you get 255.

You can convert this expression to Java with a conditional:

dst[x] = (kHit >= kForeground) ? 255 : 0;

Because of branching, it is not going to be as fast as the original one. There's little you can do about the speed of it, however, as Java lacks abilities to re-interpret boolean values as numerics.

نصائح أخرى

kHit >= kForeground returns either true or false, which in C++ sort of means 1 or 0. The minus in front transforms this to -1 or 0. The cast to uchar ((uchar)) returns 0 for 0 and wraps to 255 for the negative -1.

Following Konrad's comment, I'm also skeptical this is well defined. It is well defined, but it's still an awful piece of code in terms of readability. :)

What it basically does is following:

kHit >= kForeground

is an expression of type bool

-(kHit >= kForeground)

converts this bool into an int (based on true==1 and false==0) and negates it, which results in true==-1 and false==0.

This is then converted into a uchar, which results in -1==255 and 0==0.

It has to be noted that though seeming as using the underlying implementation details of the numbers, all those conversions are guaranteed by the C++ and C standards, as negative unsigned numbers are specified to behave according to twos-complement.

But if Java doesn't support this, you can always replace it by a conditional assignment:

dst[x] = (kHit>=kForeground) ? 255 : 0;

The expression (kHit >= kForeground) yields a boolean that has value true or false. When the unary - is applied, the bool gets promoted to an int, and the conversion yields 1 for true or 0 for false. After the promotion, the sign is changed into -1 or 0 and then it is converted to uchar by the outer cast.

Note that the important bit of information is that the unary operator- is not applied to a boolean, but the boolean is converted to int and it is then applied. That can be tested with a bit of template magic:

template <typename T, typename U>
struct same_type {
    static const bool value = false;
};
template <typename T>
struct same_type<T,T> {
    static const bool value = true;
};
template <typename T>
void f( T value ) {
    std::cout << "Is int? " << std::boolalpha << same_type<T, int>::value << "\n";
    std::cout << "Is bool? " << same_type<T, bool>::value << "\n";
}
int main() {
    f(-true);
}

The f template tests the type of the passed argument against int and bool by using the same_type templates above (trivial enough to understand). If we call the f template with -true as argument type deduction will set T to be the type of the expression -true. If you run the program, you will see that it prints Is int? true\nIs bool? false.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top