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
View Code

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 }
View Code

 

posted on 2017-03-27 14:19  半日闲心  阅读(1514)  评论(0)    收藏  举报

导航