将opencv Mat格式的图像数据写入excel表格
在学习opencv的过程中,我经常想了解当前图像某个区域的具体像素值及其分布规律。如果将数据打印在控制台中,会觉得眼花缭乱,很难找到想关注的内容。但如果可以将其输出到excel表格中,查看起来就会方便很多,辅以简单的VB程序,还可以让不同的数据显示不同的颜色,数据查看会更加直观。本文记录将Mat图像写入excel表格和为excel表格数值赋颜色的方法,欢迎指点。
将Mat图像写入excel表格
以《connectedComponentsWithStats在汉字定位中的应用》提到的SWT图像为例,我可以将不同连通域的笔画宽度值分布绘图表示,这样就可以比较清楚直观的观察到笔画分布状况。将下图左边图像命令为“九节属”,右边图像是“九节属”经过SWT,连通域和某种过滤后,剩余的连通域及其标号的图像。
我将“九节属”过滤之后的剩余区域的SWT图像写入Excel表格,其中包含“九”的区域数据的缩小和放大图如下图。由下图可知,Excel表格缩小之后,可以看见字体的轮廓,可以比较方便的选择想关注的区域并放大,即可清晰的看到该区域的数据。
对“九节属”过滤之后剩余的连通域求取各笔画宽度值的直方图,将直方图写入Excel表格,然后借助Excel可以将各种笔画值数量占连通域总数量的比值在Excel表格中绘制成图,这样可以更直观的将图像特征展现出来。连通域中标号从0开始,而Excel表格中行的标号从1开始,因此下图中的标号=连通域过滤图标号+1。
将Mat数据输出至excel表格的代码如下,下面函数所需要的参数fileName需要后缀名,若要求存储类型为表格时,该参数应该为fileName.xls;该函数也可用于将数据写入txt文档,同理,修改文件的后缀名即可。我验证过xls和txt文件,理论上也适用于写入其他类型的文件,有兴趣的同学可以尝试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
void writeToExcel(Mat outputImage, string fileName) { ofstream Fs(fileName); if (!Fs.is_open()) { cout << "error!" << endl; return; } int channels = outputImage.channels(); //获取图像channel int nrows = outputImage.rows; //矩阵的行数 int ncols = outputImage.cols*channels; //矩阵的总列数=列数*channel分量数 //循环用变量 int i = 0; int j = 0; if (outputImage.depth() == CV_8U)//uchar { for (i = 0; i<nrows; i++) { for (j = 0; j<ncols; j++) { int tmpVal = (int)outputImage.ptr<uchar>(i)[j]; Fs << tmpVal << '\t'; } Fs << endl; } } else if (outputImage.depth() == CV_16S)//short { for (i = 0; i<nrows; i++) { for (j = 0; j<ncols; j++) { Fs << (short)outputImage.ptr<short>(i)[j] << '\t'; } Fs << endl; } } else if (outputImage.depth() == CV_16U)//unsigned short { for (i = 0; i<nrows; i++) { for (j = 0; j<ncols; j++) { Fs << (unsigned short)outputImage.ptr<unsigned short>(i)[j] << '\t'; } Fs << endl; } } else if (outputImage.depth() == CV_32S)//int { for (i = 0; i<nrows; i++) { for (j = 0; j<ncols; j++) { Fs << (int)outputImage.ptr<int>(i)[j] << '\t'; } Fs << endl; } } else if (outputImage.depth() == CV_32F)//float { for (i = 0; i<nrows; i++) { for (j = 0; j<ncols; j++) { Fs << (float)outputImage.ptr<float>(i)[j] << '\t'; } Fs << endl; } } else//CV_64F double { for (i = 0; i < nrows; i++) { for (j = 0; j < ncols; j++) { Fs << (double)outputImage.ptr<double>(i)[j] << '\t'; } Fs << endl; } } Fs.close(); } } |
用VB程序为不同的数据区域涂色
这里以Excel2010为例,给出一个简单的示例,其实VB和Excel结合可以实现更多更实用的功能,但这个话题并不在我们讨论的范围内。在本文的这个示例中,我将原图的灰度图数值写入Excel表格,然后通过VB代码根据单元格中的灰度值涂上相应的颜色,测试结果如下图:
在Excel2010中输入和运行VB的步骤如下:
1. 打开我们想处理的图像的Excel文件,选择“开发工具–>Visual Basic”;
2. 在弹出界面的编辑区域输入相应的VB代码,按下F5即可。
本文的记录到此结束,欢迎围观和指点,多谢。