(一)OpenCV创建显示内存图像

概述:

本例程为一个创建内存图像,并将该内存图像利用图像库OpenCV,展示到窗体上。我们将在内存创建一个640x480大小的图像,图像内容是渐变的过渡色,从黑到红。通过本章节例程的学习,我们将掌握一下几个技术点:

  1. 如何创建一个标准的内存图像数组(BGR分布)
  2. 如何理解像素格式
  3. 如何将内存数组绑定到OpenCV图像对象上并展示出来

 

Step:1:内存数组,创建内存图像

这里我们创建了一个三通道的内存图像,并将内存图像默认置为红色,内存图像的像素格式选取的BGR格式,也就是说,在这幅内存图像中,所有的像素都是按照BGR依次摆开的,所以该内存数组的大小为 width * height * 3。创建好之后将该数组遍历一遍,并将B通道像素置为255,G通道和R通道像素置为0。

unsigned char* CreateBGRMemoryImage(int nWidth, int nHeight)
{
    //我们在选取的BGR像素格式,所以一共是三个通道
    int nImgChannel = 3;
    //用来作为数组访问的索引
    int nPixelIndex = 0;
    //创建了内存数组,大小为width * height * 3
    unsigned char* pMemoryImage = new unsigned char[nWidth * nHeight * nImgChannel];
    //对内存数组进行初始化,将R通道置为255
    for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
       for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
       {
           pMemoryImage[nPixelIndex++] = 0;       // B channel
           pMemoryImage[nPixelIndex++] = 0;       // G channel
           pMemoryImage[nPixelIndex++] = 255;     // R channel
       }
    //将数组地址返回
    return pMemoryImage;
}

Step:2:像素格式,图像数据在内存里的分布方式

像素格式是图像数组里数据的分布格式,我们经常遇到的有BGR,RGB,BGRA,YUV等

正如我们在第一步创建内存数组的时候,不同的像素格式,内存数组就有不同的含义,BGR代表着像素 分布是第一个像素为B值,第二个像素为G值,第三个像素为R值,RGB则代表的恰恰相反,在RGB像素格式的内存图像中,第一个像素值为R值,第二个像素格式为G值,第三个像素格式为B值,BGRA则是多了一个通道ALPHA,YUV为另一种图像格式,和RGB颜色模型并列的YUV颜色模型。第一个像素代表Y值,第二个像素代表U值,低三个像素代表V值。

BGR和YUV也有转化公式,我们可以从网上得到。

另外我们也经常会在一些图像库中遇到这样的像素格式,以OpenCV举例,OpenCV中有一个像素格式转换CV_BGR2BGR565,BGR我们知道,是BGR分布的数组,BGR565是更为具体的内存数组格式,我们简单地为每个像素用一个8字节的unsigned char来存储,一个像素占据的内存大小为8 * 3 = 24个字节,我们的BGR可以称之为BGR888,那样就很清楚了BGR565的意思就是,对我们的BGR888做了一个优化,B通道像素保留了前5位,G通道像素保留了前6位,R通道像素保留了前5位,然后将这些像素重新进行排列。在很多图像硬件开发过程中会遇到这个问题,以此类推即可。

//对内存数组进行初始化,将R通道置为255
for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
   for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
   {
        //初始化B通道像素值
        pMemoryImage[nPixelIndex++] = 0;       // B channel
        //初始化G通道像素值
        pMemoryImage[nPixelIndex++] = 0;       // G channel
        //初始化R通道像素值
        pMemoryImage[nPixelIndex++] = 255;     // R channel
   }

Step:3:窗体展示,将内存数据利用图像库展示到窗体

OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,里面包含了很多图像的基础操作,和平台扩展,我们借助OpenCV的窗体库,来将我们的内存图像进行展示,在这个过程中,我们也将学会如何将我们的内存图像融合到其他框架里。图像框架有很多种,但掌握核心的算法,会让我们对图形图像理解更深刻,也更容易适应了纷繁复杂的要求,帮助读者达到在工作学习的过程中借助框架而不依赖框架,是本教程的意义所在。

言归正传,OpenCV里对图像的数据结构为IplImage,在最新的版本中(4.x),取消掉了C语言形式的数据结构,在该系列教程中我们依旧以此为例阐述,我们将创建的内存绑定到这个数据结构里的时候,就可以利用OpenCV的窗体库,将图像展示出来。可以这样理解

 

如果我们想借助OpenCV丰富的图像函数来进行图像操作,现在也可以进行了,因为,我们的内存数组已经转化为一个OpenCV图像对象了。具体过程为:

bool ShowBGRImage(unsigned char* pImage, int nWidth, int nHeight)
{
    //创建3通道的OpenCV图像对象
    IplImage* pSrcImage = cvCreateImage(cvSize(nWidth, nHeight), IPL_DEPTH_8U, 3);
    //获得图像对象的图像数组地址
    unsigned char* pImageData = (unsigned char*)pSrcImage->imageData;
    //赋值索引
    int nImageIndex = 0;
    //将我们的内存图像赋值到OpenCV的IplImage对象中
    for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
       for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
       {
            //OpenCV里,图像组是逐行存储的,其每一行的大小用widthStep记录,我们的每一行必须赋值到对应的OpenCV行中,在此得到OpenCV图像数组的索引
           int nCurPixelIndex = nYIndex * pSrcImage->widthStep + nXIndex * 3;
           //赋值B通道像素
           pImageData[nCurPixelIndex++] = pImage[nImageIndex++];
           //复制G通道像素
           pImageData[nCurPixelIndex++] = pImage[nImageIndex++];
           //赋值R通道像素
           pImageData[nCurPixelIndex++] = pImage[nImageIndex++];
       }
    //对OpenCV对象进行窗体展示
    cvShowImage(windowName, pSrcImage);
    //释放我们创建的OpenCV对象
    cvReleaseImage(&pSrcImage);
    return true;
}

3.工程示例

/***************************************************************************
*
*  本例程是一個如何操控内存图像的示例,并在章节1的基础上将过程动态的显示出来
*
*****************************************************************************/

#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>

#pragma comment(lib,"opencv_core341d.lib")
#pragma comment(lib,"opencv_highgui341d.lib")
using namespace std;

/**窗口Name**/
const char* windowName = "BGR Window ...  Press ESC Quit";

/************************************
*
*  創建BGR內存圖像
*
************************************/
unsigned char* CreateBGRMemoryImage(int nWidth, int nHeight);

/************************************
*
*  窗體顯示BGR內存圖像
*
************************************/
bool ShowBGRImage(unsigned char* pImage, int nWidth, int nHeight);


int main(int argc, char ** argv)
{
    //设置显示窗体的size
    int nIMGWidth = 640;
    int nIMGHeight = 480;
    double nPixelColorAdd = 255.0 / 640;

    //create memory image buffer
    unsigned char* theMemoryImage = CreateBGRMemoryImage(nIMGWidth, nIMGHeight);
    ShowBGRImage(theMemoryImage, nIMGWidth, nIMGHeight);
    cvWaitKey(0);

    delete[] theMemoryImage;
    return 0;

}


unsigned char* CreateBGRMemoryImage(int nWidth, int nHeight)
{
    int nImgChannel = 3;
    int nPixelIndex = 0;
    unsigned char* pMemoryImage = new unsigned char[nWidth * nHeight * nImgChannel];

    for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
       for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
       {
           pMemoryImage[nPixelIndex++] = 0;        // B channel
           pMemoryImage[nPixelIndex++] = 0;       // G channel
           pMemoryImage[nPixelIndex++] = 255;         // R channel
       }

    return pMemoryImage;
}


bool ShowBGRImage(unsigned char* pImage, int nWidth, int nHeight)
{
    IplImage* pSrcImage = cvCreateImage(cvSize(nWidth, nHeight), IPL_DEPTH_8U, 3);
    unsigned char* pImageData = (unsigned char*)pSrcImage->imageData;
    int nImageIndex = 0;

    //fill memory img to cvbuffer
    for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
       for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
       {
           int nCurPixelIndex = nYIndex * pSrcImage->widthStep + nXIndex * 3;
           pImageData[nCurPixelIndex++] = pImage[nImageIndex++];
           pImageData[nCurPixelIndex++] = pImage[nImageIndex++];
           pImageData[nCurPixelIndex++] = pImage[nImageIndex++];
       }

    cvShowImage(windowName, pSrcImage);
    cvReleaseImage(&pSrcImage);
    return true;
}

4.效果图

4.1初始化为红色

    for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
       for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
       {
           pMemoryImage[nPixelIndex++] = 0;           // B channel
           pMemoryImage[nPixelIndex++] = 0;           // G channel
           pMemoryImage[nPixelIndex++] = 255;         // R channel
       }

 

 

4.2初始化为蓝色

    for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
       for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
       {
           pMemoryImage[nPixelIndex++] = 255;       // B channel
           pMemoryImage[nPixelIndex++] = 0;         // G channel
           pMemoryImage[nPixelIndex++] = 0;         // R channel
       }

 

4.3初始化为护眼色

    for (int nYIndex = 0; nYIndex < nHeight; nYIndex++)
       for (int nXIndex = 0; nXIndex < nWidth; nXIndex++)
       {
           pMemoryImage[nPixelIndex++] = 128;      // B channel
           pMemoryImage[nPixelIndex++] = 128;       // G channel
           pMemoryImage[nPixelIndex++] = 0;         // R channel
       }

 

结语:

在本章节中,我们学会了如何创建一个BGR图像格式的内存数组,并利用OpenCV图像库,将我们的图像数据展示到窗体

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

碳纤维石头君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值