前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >VS2008 + Opencv2.1 读取图片像素输出至Excel文件

VS2008 + Opencv2.1 读取图片像素输出至Excel文件

作者头像
s1mba
发布2018-01-03 17:36:55
发布2018-01-03 17:36:55
1.9K00
代码可运行
举报
文章被收录于专栏:开发与安全开发与安全
运行总次数:0
代码可运行

系统环境:

win 7 + VS2008 + Opencv2.1 + Excel 2010

思路:先通过Opencv库函数读取图片存储至IplImage结构体中,接着通过OLE/COM方式实现对excel文件的写入,对多个单元格的读写操作可以通过CRange中以下两个成员函数来完成。VARIANT get_Value2(); void put_Value2(VARIANT& newValue); 其中,输入参数newValue只要输入一个二维数组,即可实现向Excel中一次写入多个单元格的值。前提是程序能够通过识别图片的大小而设置二维数组的起始点,举例来说,Excel 2010 里一共有1048576行, XFD列,X是26个字母中第24个字母,F是第6个,D是第4个,因此XFD对应的是 24*26*26+6*26+4=16384,图片的高度即Excel中的行数,将图片的宽度对26进行取商求余的操作可得到由字母表示的对应的列数。

操作过程:

1、新建C++工程

新建自己的C++工程。

2、添加Excel类库

在工程名上右键,选择Add---Class,选择MFC Class From TypeLib,如图:

然后添加如图的几个类。

3. 修改头文件

进入刚添加进来的几个类头文件中将#import开头的这句注掉

// 从类型库向导中用“添加类”创建的计算机生成的 IDispatch 包装类 //#import "D:\\Program Files\\Microsoft Office\\Office14\\EXCEL.EXE" no_namespace // CApplication 包装类

4、修改提示的错误

将修改过的工程编译一下,出现如下错误:

双击提示,在DialogBox()前加一下划线即可。

5、添加头文件

在使用导出功能的文件中添加头文件(包括opencv头文件):

#include "CApplication.h" #include "CFont0.h" #include "CRange.h" #include "CWorkbook.h" #include "CWorkbooks.h" #include "CWorksheet.h" #include "CWorksheets.h" #include "afxdisp.h" #include "comutil.h" #include <cv.h> #include <cxcore.h> #include <highgui.h> #include <stdlib.h>

6、使用Excel类库提供的函数将需要导出的数据导出为.xlsx文件

经过以上几步,现在可以使用Excel类库提供的函数导出数据了。与网上许多文章相对比一下,导出流程一样。只不过类库函数有所改变。函数名由Get改为get_,Set改为put_,代码如下。

说明:

1.pimg的类型 是 IplImage*,opencv库函数读取进来的图片存储在结构体 IplImage中。

2.由于初始的应用是想读出灰度图的像素值,故只输出了一个通道的值,其余两个通道可以照推。

3.如果读取的图片宽度大于256,则输出的excel文件若使用wps打开只能看到最大列为256,excel2007以上可以看到全部数值。

代码语言:cpp
代码运行次数:0
复制
void CSpectrumProDoc::OnExportexcel()
{
    // TODO: 在此添加命令处理程序代码
    CString sPath = _T("D:\\Image\\"); //注意不能是c盘的路径,没有权限写入
    CTime time = CTime::GetCurrentTime();
    CString sfilename ;
    sfilename.Format("E%02d%02d%02d%02d%02d", time.GetMonth(), time.GetDay(),
                     time.GetHour(), time.GetMinute(), time.GetSecond());
    /* 生成的文件若使用wps打开则只能看到最大列为256 */
    CString strFile = sPath + sfilename + _T(".xlsx");
    CApplication app;
    CWorkbook book;
    CWorkbooks books;
    CWorksheet sheet;
    CWorksheets sheets;
    CRange range;
    CFont0 font;
    CRange cols;
    LPDISPATCH lpDisp = NULL;
    COleVariant covTrue((short)TRUE);
    COleVariant covFalse((short)TRUE);
    COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
    if (!app.CreateDispatch("Excel.Application"))
    {
        AfxMessageBox("未能创建Excel应用程序!");
        return ;
    }
    books = app.get_Workbooks();
    book = books.Add(covOptional);
    sheets = book.get_Worksheets();
    sheet = sheets.get_Item(COleVariant((short)1));
    //  range = sheet.get_Range(COleVariant("A1"), COleVariant("A1"));
    //  range.put_Value2(COleVariant("hello excel!"));
    //************************************************************
    CString height;
    if (pimg->height > 1000)
    {
        char buf1[5] = {0}; //注意末尾需要以'\0'结尾
        height = itoa(pimg->height, buf1, 10);
    }
    else
    {
        char buf1[4] = {0};
        height = itoa(pimg->height, buf1, 10);
    }
    char buf2[4] = {0}; //注意末尾需要以'\0'结尾
    buf2[0] = pimg->width / (26 * 26) + 64;
    CString dest;
    if (buf2[0] == 64)
    {
        buf2[1] = pimg->width / 26 + 64;
        buf2[2] = pimg->width  % 26 + 64;
        char buf3[3] = {buf2[1], buf2[2], buf2[3]};
        CString temp;
        temp.Format("%s", buf3);
        dest = temp + height;
    }
    else
    {
        buf2[1] = (pimg->width - (buf2[0] - 64) * 26 * 26) / 26 + 64;
        buf2[2] = (pimg->width - (buf2[0] - 64) * 26 * 26) % 26 + 64;
        CString temp;
        temp.Format("%s", buf2);
        dest = temp + height;
    }
    /*向Sheet中写入多个单元格,规模由读取的图片决定 */
    lpDisp = sheet.get_Range(_variant_t("A1"), _variant_t(dest));
    range.AttachDispatch(lpDisp);
    VARTYPE vt = VT_I4; /*数组元素的类型,long */
    SAFEARRAYBOUND sabWrite[2]; /*用于定义数组的维数和下标的起始值*/
    sabWrite[0].cElements = pimg->width;
    sabWrite[0].lLbound = 0;
    sabWrite[1].cElements = pimg->height;
    sabWrite[1].lLbound = 0;
    COleSafeArray olesaWrite;
    olesaWrite.Create(vt, sizeof(sabWrite) / sizeof(SAFEARRAYBOUND), sabWrite);
    /*通过指向数组的指针来对二维数组的元素进行间接赋值*/
    long (*pArray)[2] = NULL;
    olesaWrite.AccessData((void **)&pArray);
    memset(pArray, 0, sabWrite[0].cElements * sabWrite[1].cElements * sizeof(long));
    /*释放指向数组的指针*/
    olesaWrite.UnaccessData();
    pArray = NULL;
    /*对二维数组的元素进行逐个赋值*/
    long index[2] = {0, 0};
    long lFirstLBound = 0;
    long lFirstUBound = 0;
    long lSecondLBound = 0;
    long lSecondUBound = 0;
    olesaWrite.GetLBound(1, &lFirstLBound);
    olesaWrite.GetUBound(1, &lFirstUBound);
    olesaWrite.GetLBound(2, &lSecondLBound);
    olesaWrite.GetUBound(2, &lSecondUBound);
    for (long i = lFirstLBound; i <= lFirstUBound; i++)
    {
        index[0] = i;
        for (long j = lSecondLBound; j <= lSecondUBound; j++)
        {
            index[1] = j;
            /* 经测试,24位深图片为8bit 3通道,灰度图(RGB都相等) */
            /* 如果是8bit 1通道的图像 I(x,y) ~ ((uchar*)(img->imageData + img->widthStep*y))[x] */
            long lElement = ((uchar *)(pimg->imageData + pimg->widthStep * j))[i * 3];
            olesaWrite.PutElement(index, &lElement);
        }
    }
    /*把ColesaWritefeArray变量转换为VARIANT,并写入到Excel表格中*/
    VARIANT varWrite = (VARIANT)olesaWrite;
    range.put_Value2(varWrite);
    //*******************************************************************
    font = range.get_Font();
    font.put_Bold(COleVariant((short)TRUE));
    cols = range.get_EntireColumn();
    cols.AutoFit();
    app.put_Visible(TRUE);
    app.put_UserControl(TRUE);
    book.SaveCopyAs(COleVariant(strFile));
    /*
        book.SaveAs(_variant_t(strFile), _variant_t((long)51),
         vtMissing, vtMissing, vtMissing, vtMissing, 0, vtMissing, vtMissing, vtMissing,
         vtMissing, vtMissing);
    */
    book.put_Saved(TRUE);
    book.ReleaseDispatch();
    books.ReleaseDispatch();
    app.Quit();
    app.ReleaseDispatch();
    AfxMessageBox("输出图像像素数据至excel文件成功");
}

输出的文件如图:

参考:

http://hfp0601.blog.163.com/blog/static/228483522011031104718762/

http://www.cnblogs.com/xianyunhe/archive/2011/09/25/2190485.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2013-04-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档