Most efficient way to clamp values in an OpenCv Mat
Asked Answered
R

1

11

I have an OpenCv Mat that I'm going to use for per-pixel remapping, called remap, that has CV_32FC2 elements.

Some of these elements might be outside of the allowed range for the remap. So I need to clamp them between Point2f(0, 0) and Point2f(w, h). What is the shortest, or most efficient, way of accomplishing this with OpenCv 2.x?

Here's one solution:

void clamp(Mat& mat, Point2f lowerBound, Point2f upperBound) {
    vector<Mat> matc;
    split(mat, matc);
    min(max(matc[0], lowerBound.x), upperBound.x, matc[0]);
    min(max(matc[1], lowerBound.y), upperBound.y, matc[1]);
    merge(matc, mat);   
}

But I'm not sure if it's the shortest, or if split/merge is efficient.

Reremouse answered 26/9, 2011 at 9:8 Comment(0)
M
1

Try splitting, using cvThreshold and then merging. You may also get away with using cvSetImageCOI to avoid the splitting. I'm not sure if thresholding code supports the COI.

You may want to profile both versions and compare their performance. I have a feeling it will do the same thing.

Masturbate answered 26/9, 2011 at 12:7 Comment(4)
Thanks for the comment, but I'm not sure how threshold could be used to do clamping more effectively than I show above with min/max. And after reading a bit more, it looks like split/merge are the C++ equivalents of cvSetImageCOI/cvGetImageCOI.Reremouse
split and merge in the C++ interface correspond to cvSplit and cvMerge functions in the C interface. Splitting is different to setting the COI -- the former actually moves data from the source to the destination, while the latter just modifies the image object header. Same for merging. Looking for ways to avoiding the split/merge may be your best bet at improving performance. I can't really guarantee that it will be more efficient (you meant efficient, not effective, right?) -- your best bet may be just to compare different implementations and run with the one that is faster.Masturbate
Yes, definitely meant "efficient" and not "effective". Thanks for clarifying cvSplit/cvMerge, I must have understood the 2.3 refman. I guess there's no 2.x way to do COI then?Reremouse
There don't seem to be many references to the COI in the C++ section of the manual. Either the C++ COI way is really cryptic, or it doesn't exist. You can still use the old C interface with C++ code (it's a bit ugly but it will work). The underlying storage for struct IplImage and cv::Mat is the same, so you can convert between the two with relatively little overhead. It will make your code uglier, but if using the COI instead of splitting gets the job done, then it may be worth it.Masturbate

© 2022 - 2024 — McMap. All rights reserved.