问题描述
给定的a CV_32SC1 cv::Mat图像包含每个像素的标签(其中标签只是0..N-1>>>>),openCV中最清洁的代码生成了一个CV_8UC3图像,该图像显示每个连接的组件都带有每个连接的组件不同的任意颜色?如果我不必像cv::floodFill那样手动指定颜色.
更好.推荐答案
如果标签的最大数量为256,则可以使用 applyColorMap ,将图像转换为CV_8U:
Mat1i img = ... // Convert to CV_8U Mat1b img2; img.convertTo(img2, CV_8U); // Apply color map Mat3b out; applyColorMap(img2, out, COLORMAP_JET);
如果标签数量高于256,则需要自己动手.下面有一个示例生成JET COLORMAP(基于jet函数的MATLAB实现).然后,您可以为矩阵的每个元素应用colormap.
请注意,如果您想要其他colormap或随机颜色,则只需要修改//Create JET colormap零件:
#include <opencv2/opencv.hpp> #include <algorithm> using namespace std; using namespace cv; void applyCustomColormap(const Mat1i& src, Mat3b& dst) { // Create JET colormap double m; minMaxLoc(src, nullptr, &m); m++; int n = ceil(m / 4); Mat1d u(n*3-1, 1, double(1.0)); for (int i = 1; i <= n; ++i) { u(i-1) = double(i) / n; u((n*3-1) - i) = double(i) / n; } vector<double> g(n * 3 - 1, 1); vector<double> r(n * 3 - 1, 1); vector<double> b(n * 3 - 1, 1); for (int i = 0; i < g.size(); ++i) { g[i] = ceil(double(n) / 2) - (int(m)%4 == 1 ? 1 : 0) + i + 1; r[i] = g[i] + n; b[i] = g[i] - n; } g.erase(remove_if(g.begin(), g.end(), [m](double v){ return v > m;}), g.end()); r.erase(remove_if(r.begin(), r.end(), [m](double v){ return v > m; }), r.end()); b.erase(remove_if(b.begin(), b.end(), [](double v){ return v < 1.0; }), b.end()); Mat1d cmap(m, 3, double(0.0)); for (int i = 0; i < r.size(); ++i) { cmap(int(r[i])-1, 2) = u(i); } for (int i = 0; i < g.size(); ++i) { cmap(int(g[i])-1, 1) = u(i); } for (int i = 0; i < b.size(); ++i) { cmap(int(b[i])-1, 0) = u(u.rows - b.size() + i); } Mat3d cmap3 = cmap.reshape(3); Mat3b colormap; cmap3.convertTo(colormap, CV_8U, 255.0); // Apply color mapping dst = Mat3b(src.rows, src.cols, Vec3b(0,0,0)); for (int r = 0; r < src.rows; ++r) { for (int c = 0; c < src.cols; ++c) { dst(r, c) = colormap(src(r,c)); } } } int main() { Mat1i img(1000,1000); randu(img, Scalar(0), Scalar(10)); Mat3b out; applyCustomColormap(img, out); imshow("Result", out); waitKey(); return 0; }
问题描述
Given a CV_32SC1 cv::Mat image that contains a label for each pixel (where a label is just an index in 0..N-1), what is the cleanest code in OpenCV to generate a CV_8UC3 image that shows each connected component with a different arbitrary color? If I don't have to specify the colors manually, as with cv::floodFill, the better.
推荐答案
If the max number of labels is 256, you can use applyColorMap, converting the image to CV_8U:
Mat1i img = ... // Convert to CV_8U Mat1b img2; img.convertTo(img2, CV_8U); // Apply color map Mat3b out; applyColorMap(img2, out, COLORMAP_JET);
If the number of labels is higher than 256, you need to do it yourself. Below there is an example that generates a JET colormap (it's based on Matlab implementation of the jet function). Then you can apply the colormap for each element of your matrix.
Please note that if you want a different colormap, or random colors, you just need to modify the //Create JET colormap part:
#include <opencv2/opencv.hpp> #include <algorithm> using namespace std; using namespace cv; void applyCustomColormap(const Mat1i& src, Mat3b& dst) { // Create JET colormap double m; minMaxLoc(src, nullptr, &m); m++; int n = ceil(m / 4); Mat1d u(n*3-1, 1, double(1.0)); for (int i = 1; i <= n; ++i) { u(i-1) = double(i) / n; u((n*3-1) - i) = double(i) / n; } vector<double> g(n * 3 - 1, 1); vector<double> r(n * 3 - 1, 1); vector<double> b(n * 3 - 1, 1); for (int i = 0; i < g.size(); ++i) { g[i] = ceil(double(n) / 2) - (int(m)%4 == 1 ? 1 : 0) + i + 1; r[i] = g[i] + n; b[i] = g[i] - n; } g.erase(remove_if(g.begin(), g.end(), [m](double v){ return v > m;}), g.end()); r.erase(remove_if(r.begin(), r.end(), [m](double v){ return v > m; }), r.end()); b.erase(remove_if(b.begin(), b.end(), [](double v){ return v < 1.0; }), b.end()); Mat1d cmap(m, 3, double(0.0)); for (int i = 0; i < r.size(); ++i) { cmap(int(r[i])-1, 2) = u(i); } for (int i = 0; i < g.size(); ++i) { cmap(int(g[i])-1, 1) = u(i); } for (int i = 0; i < b.size(); ++i) { cmap(int(b[i])-1, 0) = u(u.rows - b.size() + i); } Mat3d cmap3 = cmap.reshape(3); Mat3b colormap; cmap3.convertTo(colormap, CV_8U, 255.0); // Apply color mapping dst = Mat3b(src.rows, src.cols, Vec3b(0,0,0)); for (int r = 0; r < src.rows; ++r) { for (int c = 0; c < src.cols; ++c) { dst(r, c) = colormap(src(r,c)); } } } int main() { Mat1i img(1000,1000); randu(img, Scalar(0), Scalar(10)); Mat3b out; applyCustomColormap(img, out); imshow("Result", out); waitKey(); return 0; }