Reputation: 1203
I am trying to write code to convert an opencv
image to a QImage
. I want to implement this as a generic function using templates. This is what I have:
#include <QImage>
#include <opencv2/core/core.hpp>
void setPixel(int j, int i, unsigned char v, QImage & img)
{
img.setPixel(j, i, qRgb(v, v, v));
}
void setPixel(int j, int i, cv::Vec3b v, QImage & img)
{
img.setPixel(j, i, qRgb(v[2], v[1], v[0]));
}
template <typename ImageType>
QImage toQImageARGB (const cv::Mat & image)
{
QImage res(image.cols, image.rows, QImage::Format_ARGB32_Premultiplied);
ImageType tmp;
for (int i = 0; i < image.rows; ++i)
{
for (int j = 0; j < image.cols; ++j)
{
tmp = image.at<ImageType>(i,j);
setPixel(j, i, tmp, res);
}
}
return res;
}
I get the following compile time error
CMakeFiles/annotate.dir/main.cpp.o: In function `std::remove_reference<cv::ximgproc::SuperpixelSEEDS*&>::type&& std::move<cv::ximgproc::SuperpixelSEEDS*&>(cv::ximgproc::SuperpixelSEEDS*&)':
.../util.h:8: multiple definition of `setPixel(int, int, unsigned char, QImage&)'
CMakeFiles/annotate.dir/moc_widget.cxx.o:.../build/../util.h:8: first defined here
CMakeFiles/annotate.dir/main.cpp.o: In function `cv::Vec<unsigned char, 3> const& cv::Mat::at<cv::Vec<unsigned char, 3> >(int, int) const':
.../util.h:13: multiple definition of `setPixel(int, int, cv::Vec<unsigned char, 3>, QImage&)'
CMakeFiles/annotate.dir/moc_widget.cxx.o:.../build/../util.h:13: first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [...] Error 1
make[1]: *** [CMakeFiles/annotate.dir/all] Error 2
make: *** [all] Error 2
from my main method.
Is it possible to do this with function templates, and does it make sense?
Upvotes: 1
Views: 289
Reputation: 126542
It seems those function definitions (in particular, the two non-template overloads of setPixel()
) come from a header file that gets included into more than one translation unit (i.e. .cpp
file), thus violating the One Definition Rule.
If you want those functions' definitions to appear in the header file, declare them as inline
:
inline void setPixel(int j, int i, unsigned char v, QImage & img)
{
img.setPixel(j, i, qRgb(v, v, v));
}
inline void setPixel(int j, int i, cv::Vec3b v, QImage & img)
{
img.setPixel(j, i, qRgb(v[2], v[1], v[0]));
}
Upvotes: 2