I would like to access the elements of a matrix of unknown type:
for(int ii = 0; ii < origCols; ii++)
{
colIdx.at<img.type()>(0,ii) = ii+1; // make one based index
}
The expression defining the type (inside the <>) has to be a constant, so the above code will not work. Is there a way to do this other than just switching across the different image types?
After looking through some of the docs, I don't think there is a native OpenCV way to do it without avoiding branching.
If you are just concerned about cleaner code, you could try a template approach so long as you don't mind templates:
template <typename T> void dostuff(cv::Mat& colIdx, int origCols)
{
for(int ii = 0; ii < origCols; ii++)
{
colIdx.at<T>(0,ii) = (T)(ii+1); // make one based index
}
}
void dostuff_poly(cv::Mat& colIdx, int origCols)
{
switch(colIdx.type())
{
case CV_8UC1: dostuff<char>(colIdx, origCols); break;
case CV_32FC1: dostuff<float>(colIdx, origCols); break;
case CV_64FC1: dostuff<double>(colIdx, origCols); break;
// and so on
default:
}
}
In this example, the code is rather small, so templates seems like it wouldn't be a bad choice and would give you the polymorphism you want without writing a bunch of redundant code.
Maybe some of these tutorials would give you a better idea:
OpenCV docs: core module tutorials
OpenCV docs: How to scan images
There is no native Opencv solution to your problem, and it is a frequent pain with this library. There are three possible solutions:
Create a "smart" iterator class that will know how to access matrix data based on the matrix depth. Something like:
class PtrMat
{
PtrMat(cv::Mat& mat, int row)
{
if(mat.depth() == CV_32F) { _ptr = new PtrFloat(mat, row); }
else if(mat.depth() == CV_8U) { _ptr = new PtrUchar(mat, row); }
...
}
Ptr* _ptr
};
class Ptr
{
virtual void set(const float& val)=0;
};
class PtrFloat: public Ptr
{
PtrFloat(const cv::Mat& mat, int row){ _val = mat.ptr<float>(row); }
void set(const float& val) { _val = val; }
float* _val;
}
class PtrUchar: public Ptr
{
PtrUchar(const cv::Mat& mat, int row){ _val = mat.ptr<uchar>(row); }
void set(const float& val) { _val = val; }
uchar* _val;
}
Of course, with the third solution you end up with lots of duplicated code. Float casting can also slow down your loops. No solution is perfect in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With