C/C++调用opencv可视化矩阵<代码>
如深度图或者灰度图,转换为彩色图使数值的变化更加直观。
VisualizationTool.h
1 //http://www.cnblogs.com/easymind223 2 3 4 #pragma once 5 #ifndef _VISUALIZATION_TOOL_H_ 6 #define _VISUALIZATION_TOOL_H_ 7 8 #include "opencv2/opencv.hpp" 9 using namespace cv; 10 11 #define HIST_TYPE_MIX 0 12 #define HIST_TYPE_CONTOUR 1 13 14 namespace VisualizationTool 15 { 16 17 //深度显示单通道uchar,float, int类型图像, 18 void imageSC(std::string windowName, const Mat imgC1); 19 20 //以柱状图显示数组,array必须为 CV_32F,CV_32S,CV_8U中的一种,且rows == 1 21 void ShowArrayHistogram(std::string title, Mat array, Size size = Size(400,400)); 22 23 //显示一幅图像的直方图,histType为显示方式,HIST_TYPE_MIX表示三通道混合显示,HIST_TYPE_CONTOUR表示以轮廓显示 24 void showImageHistogram(const std::string windowName, const Mat src, 25 const Mat mask = Mat(), int histType = HIST_TYPE_MIX, 26 Size windowSize = Size(256, 200)); 27 28 //显示一幅图像的颜色分布图 29 void showImageColorDistribution(const std::string windowName, const Mat src_3u, 30 int nBins = 32, const Mat mask = Mat(), Size windowSize = Size(256, 200)); 31 32 } 33 #endif
VisualizationTool.cpp
1 #include "VisualizationTool.h" 2 using namespace cv; 3 4 namespace VisualizationTool 5 { 6 7 void imageSC(std::string windowName, const Mat imgC1) 8 { 9 assert(imgC1.channels() == 1 && !imgC1.empty()); 10 11 //get min max value of the mat 12 double minPixelValue, maxPixelValue; 13 minMaxIdx(imgC1, &minPixelValue, &maxPixelValue); 14 double valueRange = maxPixelValue - minPixelValue; 15 16 //init color table 17 const int minSaturation = 20; 18 const int colorTableLength = (255 - minSaturation) * 4; // r -> g -> b 19 Scalar colorTable[colorTableLength]; 20 21 int i,j; 22 for (i = 0, j = minSaturation; i < colorTableLength / 4; i++, j++) 23 colorTable[i] = CV_RGB(255, j, minSaturation); 24 for (i = colorTableLength / 4, j=1; i < colorTableLength / 2; i++, j++) 25 colorTable[i] = CV_RGB(255 - j, 255, minSaturation); 26 for (i = colorTableLength/2, j=minSaturation; i < colorTableLength/4*3; i++, j++) 27 colorTable[i] = CV_RGB(minSaturation, 255, j); 28 for (i = colorTableLength/4*3, j=1; i < colorTableLength; i++, j++) 29 colorTable[i] = CV_RGB(minSaturation, 255 - j, 255); 30 31 32 //draw color table 33 const int margin = 20; 34 const int tableHeight = 300;; 35 const int tableWidth = 150; 36 const int barWidth = 30; 37 const int barHeight = tableHeight - margin * 2; 38 float scale = (float)barHeight / colorTableLength; 39 40 int imageHeight = max(imgC1.rows, tableHeight); 41 int imageWidth = imgC1.cols + tableWidth; 42 Mat img3u( imageHeight, imageWidth, CV_8UC3, Scalar::all(0)); 43 44 for (int i=0; i<barHeight; i++) 45 { 46 Point pt1(imgC1.cols + margin, margin + i); 47 Point pt2(imgC1.cols + margin + barWidth, margin + i); 48 line(img3u, pt1, pt2, colorTable[cvRound(i/scale)], 1); 49 } 50 51 //illustration 52 for (int i=0; i<5; i++) 53 { 54 float value = (float)(minPixelValue + i / 4.0 * valueRange); 55 std::stringstream s; 56 s<<value; 57 int bx = imgC1.cols + margin + barWidth; 58 int by = tableHeight - margin - barHeight / 4 * i ; 59 line(img3u, Point(bx+5, by), Point(bx+10, by), cvScalarAll(255), 2); 60 putText(img3u, s.str(), Point(bx + 20, by + 8), 61 CV_FONT_HERSHEY_SIMPLEX, 0.6, cvScalarAll(255), 1); 62 } 63 64 //show image 65 Mat tim(imgC1.size(), CV_32F); 66 imgC1.convertTo(tim, CV_32F); 67 68 for (int y = 0; y < imgC1.rows; y++) 69 { 70 const float* srcData = tim.ptr<float>(y); 71 Vec3b* dstData = img3u.ptr<Vec3b>(y); 72 for (int x = 0; x<imgC1.cols; x++) 73 { 74 double pixel = (srcData[x] - minPixelValue) / valueRange; 75 Scalar color = colorTable[cvRound(pixel * (colorTableLength-1))]; 76 dstData[x] =Vec3b(color.val[2], color.val[1], color.val[0]); 77 } 78 } 79 imshow(windowName, img3u); 80 } 81 82 void ShowArrayHistogram(std::string title, Mat hist, Size size) 83 { 84 CV_Assert(hist.rows == 1); 85 Mat imHist = Mat::zeros(size, CV_8UC3); 86 int nBins = hist.rows*hist.cols; 87 double min, max; 88 minMaxLoc(hist, &min, &max); 89 double bin_width=(double)size.width/nBins; 90 double bin_unith=(double)size.height/max; 91 92 if(hist.type() == CV_32F) 93 { 94 float * ptr = hist.ptr<float>(0); 95 for(int i=0;i<nBins;i++) 96 { 97 Point p0=Point(i*bin_width,size.height); 98 Point p1=Point((i+1)*bin_width,size.height-ptr[i]*bin_unith); 99 rectangle(imHist, p0, p1, Scalar::all(255), -1, 0, 0); 100 } 101 } 102 if(hist.type() == CV_32S) 103 { 104 int* ptr = hist.ptr<int>(0); 105 for(int i=0;i<nBins;i++) 106 { 107 Point p0=Point(i*bin_width,size.height); 108 Point p1=Point((i+1)*bin_width,size.height-ptr[i]*bin_unith); 109 rectangle(imHist, p0, p1, Scalar::all(255), -1, 0, 0); 110 } 111 } 112 if(hist.type() == CV_8U) 113 { 114 uchar* ptr = hist.ptr<uchar>(0); 115 for(int i=0;i<nBins;i++) 116 { 117 Point p0=Point(i*bin_width,size.height); 118 Point p1=Point((i+1)*bin_width,size.height-ptr[i]*bin_unith); 119 rectangle(imHist, p0, p1, Scalar::all(255), -1, 0, 0); 120 } 121 } 122 123 namedWindow(title); 124 imshow(title, imHist); 125 } 126 127 void showImageHistogram(const std::string windowName, const Mat src, const Mat mask, int histType, Size windowSize) 128 { 129 CV_Assert(!src.empty()); 130 if (!mask.empty()) 131 { 132 CV_Assert(mask.type() == CV_8U && src.size() == mask.size()); 133 } 134 135 Mat src_3u; 136 if(src.channels()==1) 137 cvtColor(src, src_3u, CV_GRAY2RGB); 138 else 139 src_3u = src; 140 141 //shrink the src to save time 142 float th_maxSide = 300.0; 143 int maxSide = max(src_3u.cols , src_3u.rows); 144 Mat zoom_3u, zoomMask_1u; 145 146 if (maxSide > th_maxSide) 147 { 148 float scale = maxSide / th_maxSide; 149 zoom_3u.create(src_3u.rows / scale, src_3u.cols / scale, CV_8UC3); 150 resize(src_3u, zoom_3u, zoom_3u.size(), 0, 0, INTER_LANCZOS4 ); 151 152 if(!mask.empty()) 153 { 154 zoomMask_1u.create(mask.rows / scale, mask.cols / scale, CV_8U); 155 resize(mask, zoomMask_1u, zoomMask_1u.size(), 0, 0, INTER_LANCZOS4 ); 156 } 157 } 158 else 159 { 160 zoom_3u = src_3u; 161 if(!mask.empty()) 162 zoomMask_1u = mask; 163 } 164 165 std::vector<Mat> rgb_planes; 166 split(zoom_3u, rgb_planes ); 167 168 int nBins = 255; 169 170 /// 设定取值范围 ( R,G,B) ) 171 float range[] = { 0, 256 } ; 172 const float* histRange = { range }; 173 174 bool uniform = true; bool accumulate = false; 175 176 Mat r_hist, g_hist, b_hist; 177 178 /// 计算直方图: 179 calcHist( &rgb_planes[0], 1, 0, zoomMask_1u, r_hist, 1, &nBins, &histRange, uniform, accumulate ); 180 calcHist( &rgb_planes[1], 1, 0, zoomMask_1u, g_hist, 1, &nBins, &histRange, uniform, accumulate ); 181 calcHist( &rgb_planes[2], 1, 0, zoomMask_1u, b_hist, 1, &nBins, &histRange, uniform, accumulate ); 182 183 // 创建直方图画布 184 int canvasWidth = windowSize.width; 185 int canvasHeight = windowSize.height; 186 int binWidth = cvRound( (double) canvasWidth / nBins ); 187 188 Mat histImage(canvasHeight, canvasWidth, CV_8UC3, Scalar( 0,0,0) ); 189 190 /// 将直方图归一化到范围 [ 0, histImage.rows ] 191 normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); 192 normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); 193 normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); 194 195 /// 在直方图画布上画出直方图 196 if (histType == HIST_TYPE_CONTOUR) 197 { 198 for( int i = 1; i < nBins; i++ ) 199 { 200 line( histImage, Point( binWidth*(i-1), canvasHeight - cvRound(r_hist.at<float>(i-1)) ) , 201 Point( binWidth*(i), canvasHeight - cvRound(r_hist.at<float>(i)) ), 202 Scalar(255, 0, 0), 2, 8, 0 ); 203 line( histImage, Point( binWidth*(i-1), canvasHeight - cvRound(g_hist.at<float>(i-1)) ) , 204 Point( binWidth*(i), canvasHeight - cvRound(g_hist.at<float>(i)) ), 205 Scalar( 0, 255, 0), 2, 8, 0 ); 206 line( histImage, Point( binWidth*(i-1), canvasHeight - cvRound(b_hist.at<float>(i-1)) ) , 207 Point( binWidth*(i), canvasHeight - cvRound(b_hist.at<float>(i)) ), 208 Scalar( 0, 0, 255), 2, 8, 0 ); 209 } 210 } 211 else if (histType == HIST_TYPE_MIX) 212 { 213 for (int iBin=0; iBin<nBins; iBin++) 214 { 215 for (int iValue=1; iValue < r_hist.at<float>(iBin); iValue++) 216 { 217 for (int j=0; j<binWidth; j++) 218 { 219 Vec3b& pixel = histImage.at<Vec3b>(canvasHeight - iValue, iBin * binWidth + j); 220 pixel.val[0] = 255; 221 } 222 } 223 for (int iValue=1; iValue < g_hist.at<float>(iBin); iValue++) 224 { 225 for (int j=0; j<binWidth; j++) 226 { 227 Vec3b& pixel = histImage.at<Vec3b>(canvasHeight - iValue, iBin * binWidth + j); 228 pixel.val[1] = 255; 229 } 230 } 231 for (int iValue=1; iValue < b_hist.at<float>(iBin); iValue++) 232 { 233 for (int j=0; j<binWidth; j++) 234 { 235 Vec3b& pixel = histImage.at<Vec3b>(canvasHeight - iValue, iBin * binWidth + j); 236 pixel.val[2] = 255; 237 } 238 } 239 } 240 } 241 imshow(windowName, histImage ); 242 } 243 244 bool histCompare(std::pair<Scalar,int> v1, std::pair<Scalar,int> v2) 245 { 246 return v1.second < v2.second; 247 } 248 249 int countValueAppearTimes(const Mat srcC1, double value) 250 { 251 CV_Assert(!srcC1.empty() && srcC1.channels()==1); 252 253 Mat r = srcC1 - value; 254 int times = countNonZero(r); 255 return srcC1.cols * srcC1.rows - times; 256 } 257 258 void showImageColorDistribution(const std::string windowName, const Mat src_3u, int nBins, 259 const Mat mask, Size windowSize) 260 { 261 CV_Assert(!src_3u.empty() ); 262 if (!mask.empty()) 263 { 264 CV_Assert(mask.type() == CV_8U && src_3u.size() == mask.size()); 265 } 266 267 //shrink the src to save time 268 float th_maxSide = 300.0; 269 int maxSide = max(src_3u.cols , src_3u.rows); 270 Mat zoom_3u, zoomMask_1u; 271 272 if (maxSide > th_maxSide) 273 { 274 float scale = maxSide / th_maxSide; 275 zoom_3u.create(src_3u.rows / scale, src_3u.cols / scale, CV_8UC3); 276 resize(src_3u, zoom_3u, zoom_3u.size(), 0, 0, INTER_LANCZOS4 ); 277 278 if(!mask.empty()) 279 { 280 zoomMask_1u.create(mask.rows / scale, mask.cols / scale, CV_8U); 281 resize(mask, zoomMask_1u, zoomMask_1u.size(), 0, 0, INTER_LANCZOS4 ); 282 } 283 } 284 else 285 { 286 zoom_3u = src_3u; 287 if(!mask.empty()) 288 zoomMask_1u = mask; 289 } 290 int maskNonZero = countNonZero(zoomMask_1u); 291 292 //k-means cluster 293 Mat clusterMat; 294 Mat bestLabels, centers; 295 Vec3b* data = zoom_3u.ptr<Vec3b>(0); 296 if(mask.empty()) 297 { 298 clusterMat.create(zoom_3u.cols * zoom_3u.rows, 3, CV_32F); 299 for (int i=0; i<zoom_3u.cols * zoom_3u.rows; i++) 300 { 301 Vec3b pixel = data[i]; 302 clusterMat.at<float>(i, 0) = pixel.val[0]; 303 clusterMat.at<float>(i, 1) = pixel.val[1]; 304 clusterMat.at<float>(i, 2) = pixel.val[2]; 305 } 306 } 307 else 308 { 309 clusterMat.create(maskNonZero, 3, CV_32F); 310 const uchar* maskData = zoomMask_1u.ptr<uchar>(0); 311 for (int i=0, j=0; i<zoomMask_1u.cols * zoomMask_1u.rows; i++) 312 { 313 if(maskData[i] > 0) 314 { 315 Vec3b pixel = data[i]; 316 clusterMat.at<float>(j, 0) = pixel.val[0]; 317 clusterMat.at<float>(j, 1) = pixel.val[1]; 318 clusterMat.at<float>(j, 2) = pixel.val[2]; 319 j++; 320 } 321 } 322 } 323 324 kmeans(clusterMat, nBins, bestLabels, TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0), 325 3, KMEANS_PP_CENTERS, centers); 326 327 //statistics 328 std::vector<std::pair<Scalar,int>> hist(nBins); 329 for (int i=0; i<nBins; i++) 330 { 331 Scalar color( centers.at<float>(i,0), centers.at<float>(i,1), centers.at<float>(i,2)); 332 int val = countValueAppearTimes(bestLabels, i); 333 hist.at(i) = std::pair<Scalar,int>(color, val); 334 } 335 std::sort(hist.begin(), hist.end(), histCompare); 336 int maxValue = hist[nBins-1].second; 337 338 //canvas 339 float scale = (float)windowSize.height / maxValue; 340 int binWidth = windowSize.width / nBins; 341 Mat canvas(windowSize, CV_8UC3, Scalar::all(30)); 342 343 for (int i=0; i<nBins; i++) 344 { 345 Point pt1( i * binWidth, canvas.rows - 1); 346 Point pt2( (i+1) * binWidth, canvas.rows - 1 - hist[i].second * scale); 347 rectangle(canvas, pt1, pt2, hist[i].first, -1); 348 } 349 imshow(windowName, canvas); 350 } 351 352 }
浙公网安备 33010602011771号