在用opencv编程时,经常需要可视化地查看某个矩阵在运算过程中的状态如何,而opencv中的imshow函数只能以灰度显示单通道uchar或float类型的图像,其可视化效果不尽人意,为此,我写了一个矩阵可视化工具包,其中包含了一个类似于matlab中的imagesc的函数,能够以不同的颜色显示矩阵中不同大小的值,这个函数在查看矩阵时非常方便,这里贡大家参考。

VisualizationTool.h

View Code

//http://www.cnblogs.com/easymind223#pragma once
#ifndef _VISUALIZATION_TOOL_H_
#define _VISUALIZATION_TOOL_H_#include "opencv2/opencv.hpp"#define HIST_TYPE_MIX 0
#define HIST_TYPE_CONTOUR 1namespace VisualizationTool
{//深度显示单通道uchar,float, int类型图像,
void imageSC(std::string windowName, const cv::Mat imgC1);//以柱状图显示数组,array必须为 CV_32F,CV_32S,CV_8U中的一种,且rows == 1
void ShowArrayHistogram(std::string title, cv::Mat array, cv::Size size = cv::Size(400,400));//显示一幅图像的直方图,histType为显示方式,HIST_TYPE_MIX表示三通道混合显示,HIST_TYPE_CONTOUR表示以轮廓显示
void showImageHistogram(const std::string windowName, const cv::Mat src, const cv::Mat mask = cv::Mat(), int histType = HIST_TYPE_MIX, cv::Size windowSize = cv::Size(256, 200));//显示一幅图像的颜色分布图
void showImageColorDistribution(const std::string windowName, const cv::Mat src_3u,int nBins = 32, const cv::Mat mask = cv::Mat(), cv::Size windowSize = cv::Size(256, 200));}
#endif

VisualizationTool.cpp

View Code

#include "stdafx.h"
#include "VisualizationTool.h"namespace VisualizationTool
{void imageSC(std::string windowName, const cv::Mat imgC1)
{assert(imgC1.channels() == 1 && !imgC1.empty());//get min max value of the matdouble minPixelValue, maxPixelValue;cv::minMaxIdx(imgC1, &minPixelValue, &maxPixelValue);double valueRange = maxPixelValue - minPixelValue;//init color tableconst int minSaturation = 20;const int colorTableLength = (255 - minSaturation) * 4;    // r -> g -> b
    cv::Scalar colorTable[colorTableLength];int i,j;for (i = 0, j = minSaturation; i < colorTableLength / 4; i++, j++)colorTable[i] = CV_RGB(255, j, minSaturation);for (i = colorTableLength / 4, j=1; i < colorTableLength / 2; i++, j++)colorTable[i] = CV_RGB(255 - j, 255, minSaturation);for (i = colorTableLength/2, j=minSaturation; i < colorTableLength/4*3; i++, j++)colorTable[i] = CV_RGB(minSaturation, 255, j);for (i = colorTableLength/4*3, j=1; i < colorTableLength; i++, j++)colorTable[i] = CV_RGB(minSaturation, 255 - j, 255);//draw color tableconst int margin = 20;const int tableHeight = 300;;const int tableWidth = 150;const int barWidth = 30;const int barHeight = tableHeight - margin * 2;float scale = (float)barHeight / colorTableLength;int imageHeight = cv::max(imgC1.rows, tableHeight);int imageWidth = imgC1.cols + tableWidth;cv::Mat img3u( imageHeight, imageWidth, CV_8UC3, cv::Scalar::all(0));for (int i=0; i<barHeight; i++){cv::Point pt1(imgC1.cols + margin, margin + i);cv::Point pt2(imgC1.cols + margin + barWidth, margin + i);cv::line(img3u, pt1, pt2, colorTable[cvRound(i/scale)], 1);}//illustrationfor (int i=0; i<5; i++){float value = minPixelValue + i / 4.0 * valueRange;std::stringstream s;s<<value;int bx = imgC1.cols + margin + barWidth;int by = tableHeight - margin - barHeight / 4 * i ;cv::line(img3u, cv::Point(bx+5, by), cv::Point(bx+10, by), cvScalarAll(255), 2);cv::putText(img3u, s.str(), cv::Point(bx + 20, by + 8),CV_FONT_HERSHEY_SIMPLEX, 0.6, cvScalarAll(255), 1);}//show image
    cv::Mat tim(imgC1.size(), CV_32F);imgC1.convertTo(tim, CV_32F);for (int y = 0; y < imgC1.rows; y++){const float* srcData = tim.ptr<float>(y);cv::Vec3b* dstData = img3u.ptr<cv::Vec3b>(y);for (int x = 0; x<imgC1.cols; x++){double pixel = (srcData[x] - minPixelValue) / valueRange;cv::Scalar color = colorTable[cvRound(pixel * (colorTableLength-1))];dstData[x] =cv::Vec3b(color.val[2], color.val[1], color.val[0]);}}cv::imshow(windowName, img3u);
}void ShowArrayHistogram(std::string title, cv::Mat hist, cv::Size size)
{CV_Assert(hist.rows == 1);cv::Mat imHist = cv::Mat::zeros(size, CV_8UC3);int nBins = hist.rows*hist.cols;double min, max;cv::minMaxLoc(hist, &min, &max);double bin_width=(double)size.width/nBins;  double bin_unith=(double)size.height/max;if(hist.type() == CV_32F){float * ptr = hist.ptr<float>(0);for(int i=0;i<nBins;i++)  {  cv::Point p0=cv::Point(i*bin_width,size.height);  cv::Point p1=cv::Point((i+1)*bin_width,size.height-ptr[i]*bin_unith);  cv::rectangle(imHist, p0, p1, cv::Scalar::all(255), -1, 0, 0);} }if(hist.type() == CV_32S){int* ptr = hist.ptr<int>(0);for(int i=0;i<nBins;i++)  {  cv::Point p0=cv::Point(i*bin_width,size.height);  cv::Point p1=cv::Point((i+1)*bin_width,size.height-ptr[i]*bin_unith);  cv::rectangle(imHist, p0, p1, cv::Scalar::all(255), -1, 0, 0);} }if(hist.type() == CV_8U){uchar* ptr = hist.ptr<uchar>(0);for(int i=0;i<nBins;i++)  {  cv::Point p0=cv::Point(i*bin_width,size.height);  cv::Point p1=cv::Point((i+1)*bin_width,size.height-ptr[i]*bin_unith);  cv::rectangle(imHist, p0, p1, cv::Scalar::all(255), -1, 0, 0);} }cv::namedWindow(title);cv::imshow(title, imHist);
}void showImageHistogram(const std::string windowName, const cv::Mat src,  const cv::Mat mask, int histType, cv::Size windowSize)
{CV_Assert(!src.empty());if (!mask.empty()){CV_Assert(mask.type() == CV_8U && src.size() == mask.size());}cv::Mat src_3u;if(src.channels()==1)cv::cvtColor(src, src_3u, CV_GRAY2RGB);elsesrc_3u = src;//shrink the src to save timefloat th_maxSide = 300.0;int maxSide = cv::max(src_3u.cols , src_3u.rows);cv::Mat zoom_3u, zoomMask_1u;if (maxSide > th_maxSide){float scale = maxSide / th_maxSide;zoom_3u.create(src_3u.rows / scale, src_3u.cols / scale, CV_8UC3);cv::resize(src_3u, zoom_3u, zoom_3u.size(), 0, 0, cv::INTER_LANCZOS4 );if(!mask.empty()){zoomMask_1u.create(mask.rows / scale, mask.cols / scale, CV_8U);cv::resize(mask, zoomMask_1u, zoomMask_1u.size(), 0, 0, cv::INTER_LANCZOS4 );}}else{zoom_3u = src_3u;if(!mask.empty())zoomMask_1u = mask;}std::vector<cv::Mat> rgb_planes;cv::split(zoom_3u, rgb_planes );int nBins = 255;/// 设定取值范围 ( R,G,B) )float range[] = { 0, 256 } ;const float* histRange = { range };bool uniform = true; bool accumulate = false;cv::Mat r_hist, g_hist, b_hist;/// 计算直方图:cv::calcHist( &rgb_planes[0], 1, 0, zoomMask_1u, r_hist, 1, &nBins, &histRange, uniform, accumulate );cv::calcHist( &rgb_planes[1], 1, 0, zoomMask_1u, g_hist, 1, &nBins, &histRange, uniform, accumulate );cv::calcHist( &rgb_planes[2], 1, 0, zoomMask_1u, b_hist, 1, &nBins, &histRange, uniform, accumulate );// 创建直方图画布int canvasWidth = windowSize.width; int canvasHeight = windowSize.height;int binWidth = cvRound( (double) canvasWidth / nBins );cv::Mat histImage(canvasHeight, canvasWidth,  CV_8UC3, cv::Scalar( 0,0,0) );/// 将直方图归一化到范围 [ 0, histImage.rows ]cv::normalize(r_hist, r_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat() );cv::normalize(g_hist, g_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat() );cv::normalize(b_hist, b_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat() );/// 在直方图画布上画出直方图if (histType == HIST_TYPE_CONTOUR){for( int i = 1; i < nBins; i++ ){cv::line( histImage, cv::Point( binWidth*(i-1), canvasHeight - cvRound(r_hist.at<float>(i-1)) ) ,cv::Point( binWidth*(i), canvasHeight - cvRound(r_hist.at<float>(i)) ),cv::Scalar(255, 0, 0), 2, 8, 0  );cv::line( histImage, cv::Point( binWidth*(i-1), canvasHeight - cvRound(g_hist.at<float>(i-1)) ) ,cv::Point( binWidth*(i), canvasHeight - cvRound(g_hist.at<float>(i)) ),cv::Scalar( 0, 255, 0), 2, 8, 0  );cv::line( histImage, cv::Point( binWidth*(i-1), canvasHeight - cvRound(b_hist.at<float>(i-1)) ) ,cv::Point( binWidth*(i), canvasHeight - cvRound(b_hist.at<float>(i)) ),cv::Scalar( 0, 0, 255), 2, 8, 0  );}}else if (histType == HIST_TYPE_MIX){for (int iBin=0; iBin<nBins; iBin++){for (int iValue=1; iValue < r_hist.at<float>(iBin); iValue++){for (int j=0; j<binWidth; j++){cv::Vec3b& pixel = histImage.at<cv::Vec3b>(canvasHeight - iValue, iBin * binWidth + j);pixel.val[0] = 255;}}for (int iValue=1; iValue < g_hist.at<float>(iBin); iValue++){for (int j=0; j<binWidth; j++){cv::Vec3b& pixel = histImage.at<cv::Vec3b>(canvasHeight - iValue, iBin * binWidth + j);pixel.val[1] = 255;}}for (int iValue=1; iValue < b_hist.at<float>(iBin); iValue++){for (int j=0; j<binWidth; j++){cv::Vec3b& pixel = histImage.at<cv::Vec3b>(canvasHeight - iValue, iBin * binWidth + j);pixel.val[2] = 255;}}}}cv::imshow(windowName, histImage );
}bool histCompare(std::pair<cv::Scalar,int> v1, std::pair<cv::Scalar,int> v2)
{return v1.second < v2.second;
}int countValueAppearTimes(const cv::Mat srcC1, double value)
{CV_Assert(!srcC1.empty() && srcC1.channels()==1);cv::Mat r = srcC1 - value;int times = cv::countNonZero(r);return srcC1.cols * srcC1.rows - times;
}void showImageColorDistribution(const std::string windowName, const cv::Mat src_3u, int nBins, const cv::Mat mask, cv::Size windowSize)
{CV_Assert(!src_3u.empty() );if (!mask.empty()){CV_Assert(mask.type() == CV_8U && src_3u.size() == mask.size());}//shrink the src to save timefloat th_maxSide = 300.0;int maxSide = cv::max(src_3u.cols , src_3u.rows);cv::Mat zoom_3u, zoomMask_1u;if (maxSide > th_maxSide){float scale = maxSide / th_maxSide;zoom_3u.create(src_3u.rows / scale, src_3u.cols / scale, CV_8UC3);cv::resize(src_3u, zoom_3u, zoom_3u.size(), 0, 0, cv::INTER_LANCZOS4 );if(!mask.empty()){zoomMask_1u.create(mask.rows / scale, mask.cols / scale, CV_8U);cv::resize(mask, zoomMask_1u, zoomMask_1u.size(), 0, 0, cv::INTER_LANCZOS4 );}}else{zoom_3u = src_3u;if(!mask.empty())zoomMask_1u = mask;}int maskNonZero = countNonZero(zoomMask_1u);//k-means cluster
    cv::Mat clusterMat;cv::Mat bestLabels, centers;cv::Vec3b* data = zoom_3u.ptr<cv::Vec3b>(0);if(mask.empty()){clusterMat.create(zoom_3u.cols * zoom_3u.rows, 3, CV_32F);for (int i=0; i<zoom_3u.cols * zoom_3u.rows; i++){cv::Vec3b pixel = data[i];clusterMat.at<float>(i, 0) = pixel.val[0];clusterMat.at<float>(i, 1) = pixel.val[1];clusterMat.at<float>(i, 2) = pixel.val[2];}}else{clusterMat.create(maskNonZero, 3, CV_32F);const uchar* maskData = zoomMask_1u.ptr<uchar>(0);for (int i=0, j=0; i<zoomMask_1u.cols * zoomMask_1u.rows; i++){if(maskData[i] > 0){cv::Vec3b pixel = data[i];clusterMat.at<float>(j, 0) = pixel.val[0];clusterMat.at<float>(j, 1) = pixel.val[1];clusterMat.at<float>(j, 2) = pixel.val[2];j++;}}}cv::kmeans(clusterMat, nBins, bestLabels, cv::TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),3, cv::KMEANS_PP_CENTERS, centers);//statisticsstd::vector<std::pair<cv::Scalar,int>> hist(nBins);for (int i=0; i<nBins; i++){cv::Scalar color( centers.at<float>(i,0), centers.at<float>(i,1), centers.at<float>(i,2));int val = countValueAppearTimes(bestLabels, i);hist.at(i) = std::pair<cv::Scalar,int>(color, val);}std::sort(hist.begin(), hist.end(), histCompare);int maxValue = hist[nBins-1].second;//canvasfloat scale = (float)windowSize.height / maxValue;int binWidth = windowSize.width / nBins;cv::Mat canvas(windowSize, CV_8UC3, cv::Scalar::all(30));for (int i=0; i<nBins; i++){cv::Point pt1(  i    * binWidth, canvas.rows - 1);cv::Point pt2( (i+1) * binWidth, canvas.rows - 1 - hist[i].second * scale);        cv::rectangle(canvas, pt1, pt2, hist[i].first, -1);}cv::imshow(windowName, canvas);
}}

注意:由于博客园的bug, cpp文件中的kmeans函数会复制不全,复制以后可能会少一个参数,请仔细检查

解释一下文件中的几个函数:

1. void imageSC(std::string windowName, const cv::Mat imgC1)

深度显示单通道uchar,float, int类型图像,类似于matlab的imagesc函数,本函数还自带颜色表和矩阵的值域分布

例:

2. void showImageHistogram(const std::string windowName, const cv::Mat src, const cv::Mat mask = cv::Mat(), int histType = HIST_TYPE_MIX, cv::Size windowSize = cv::Size(256, 200));

显示一幅图像的直方图,histType为显示方式,HIST_TYPE_MIX表示三通道混合显示,HIST_TYPE_CONTOUR表示以轮廓显示,窗口的宽度最好是256的倍数。

例:

3.void showImageColorDistribution(const std::string windowName, const cv::Mat src_3u, int nBins = 32, const cv::Mat mask = cv::Mat(), cv::Size windowSize = cv::Size(256, 200));

显示一幅图像的颜色分布图,这个函数有点慢,结果也有一定的不确定性,因为用到了k-means,函数的速度取决于nBins的大小,窗口的宽度最好是256的倍数。

例:

4. void ShowArrayHistogram(std::string title, cv::Mat array, cv::Size size = cv::Size(400,400));

以柱状图显示一维数组,array必须为 CV_32F,CV_32S,CV_8U中的一种,且rows == 1,这个函数就不贴图了~

转载于:https://www.cnblogs.com/easymind223/archive/2013/03/31/2991866.html

OpenCV矩阵可视化工具包相关推荐

  1. Python中可视化工具包Matplotlib和Visdom介绍

    一.Matplotlib 简介 Matplotlib 是一个可视化工具包,可以让我们使用Python 来可视化数据. 很多更高级的绘图库,也都是基于Matplotlib,比如seaborn,HoloV ...

  2. R语言自定义多分类混淆矩阵可视化函数(mutlti class confusion matrix)、R语言多分类混淆矩阵可视化

    R语言自定义多分类混淆矩阵可视化函数(mutlti class confusion matrix).R语言多分类混淆矩阵可视化 目录

  3. Python混淆矩阵可视化:plt.colorbar函数自定义颜色条的数值标签、配置不同情况下颜色条的数值范围以及数据类型(整型、浮点型)

    Python混淆矩阵可视化:plt.colorbar函数自定义颜色条的数值标签.配置不同情况下颜色条的数值范围以及数据类型(整型.浮点型) 目录

  4. 8个流行的Python可视化工具包!!!

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 喜欢用 Python 做项目的小伙伴不免会遇到这种情况:做图表时,用哪种好看又实用 ...

  5. python可视化界面工具_8个流行的 Python可视化工具包,你喜欢哪个?

    点击上方"Python编程开发",选择"星标或者置顶" 一起高效学习Python编程开发! 编译:机器之心,作者:Aaron Frederick 喜欢用 Pyt ...

  6. Python语言学习之图表可视化:python语言中可视化工具包的简介、安装、使用方法、经典案例之详细攻略

    Python语言学习之图表可视化:python语言中可视化工具包的简介.安装.使用方法.经典案例之详细攻略 目录 python语言中可视化工具包的简介 python语言中可视化工具包的安装 pytho ...

  7. 这里有8个流行的Python可视化工具包,你喜欢哪个?

    喜欢用 Python 做项目的小伙伴不免会遇到这种情况:做图表时,用哪种好看又实用的可视化工具包呢?之前文章里出现过漂亮的图表时,也总有读者在后台留言问该图表时用什么工具做的.下面,作者介绍了八种在 ...

  8. 30.32.33.词云图、3D绘图、矩阵可视化、绘制混淆矩阵

    30.词云图(Word cloud) 30.1.Example 1: Basic word cloud 31.3D绘图 31.1.在3D图上绘制2D数据 31.2.3D 散点图 (scatterplo ...

  9. OpenCV—矩阵数据类型转换cv::convertTo

    OpenCV-矩阵数据类型转换cv::convertTo 函数 [cpp] view plaincopy void convertTo( OutputArray m, int rtype, doubl ...

最新文章

  1. HDFS数据迁移解决方案之DistCp工具的巧妙使用
  2. 计算机考试一级考试基础知识,全国计算机等级考试一级msoffice基础知识
  3. linux驱动 自旋锁
  4. c语言程序设计语言描述,C语言程序设计题目描述(详).txt
  5. Partition does not end on cylinder boundary
  6. 人人网 校内- 日志分享
  7. 0201电脑桌的制作过程(使用3DsMAX2016)
  8. 窥一斑而知全豹,几分钟带你读懂Java字节码,再也不怕了
  9. SmartGit功能介绍
  10. 移植安装ModBus到ARM开发板
  11. 简述计算机组装的具体流程,简述计算机的组装流程??
  12. 总结自己大学学习Java过程感悟
  13. 新一代态势感知系统发布——北望
  14. 《社交红利》读书总结--如何从微信微博QQ空间等社交网络带走海量用户、流量与收入...
  15. 【Springcloud】<微服务>微服务架构设计理念
  16. C语言的数据类型——基本数据类型——整形家族(字符类型)以及整形提升和截断
  17. ch03:复杂一点的查询
  18. Java 计算两个日期之间相差多少工作日
  19. 搭建阿里云Windows版服务器+使用宝塔安装MySQL数据库+本地Navicat访问数据库(增删改查)——详细流程
  20. 精读《深入了解现代浏览器二》

热门文章

  1. python怎么计算时间_python怎么计算若干分钟后是第几天,星期几
  2. aboboo 上一句 快捷键_Word快捷键大全
  3. mysql索引 钱缀_【mysql索引】之前缀索引-Go语言中文社区
  4. Java如何解析markdown_使用Java实现的一款Markdown解析器md2x
  5. python 列表 随机采样_Python 随机抽样
  6. 【深度学习】ResNet的思想
  7. Java8 Lambda不仅仅只是语法糖
  8. 淘宝分布式调度框架TBSchedule
  9. 写给程序员的有效学习方法
  10. 《卓有成效的程序员》----读书笔记二