数据结构操作与运算-IplImage数据结构操作(2)

风在竹林 posted @ 2009年8月09日 01:15 in OpenCV with tags OpenCV数据结构操作与运算 , 3797 阅读

这里就介绍算法实例让程序代码最简洁的的方式啦,跟前面直接存取不同,这边是用到OpenCV的内部函数去设计的,因此程序代码看起来简洁有力,也不需要 特意去算信道数及研究一维数组如何存取,这里的实例为二值化的程序设计(Image Thresholding),也就是图像的结果不是0就是255,甚至可以将它存入IPL_DEPTH_1U参数的制作.

IplImage数据结构二值化实例

#include <cv.h>
#include <highgui.h>
#include <stdio.h>


double Red[512][384];
double Green[512][384];
double Blue[512][384];
double Gray[512][384];

int main()
{
        int Height;
        int Width;
        int Threshold=64;
        IplImage *Image1,*Image2;
        Image1=cvLoadImage("bower.jpg",1);
        Image2=cvCloneImage(Image1);

        CvScalar Scalar1;

        Height=cvGetDimSize(Image1,0);
        Width=cvGetDimSize(Image1,1);

        /*Load Image RGB Values*/
        for(int i=0;i<Height;i++)
        {
                for(int j=0;j<Width;j++)
                {
                        Scalar1=cvGet2D(Image1,i,j);
                        Blue[i][j]=Scalar1.val[0];
                        Green[i][j]=Scalar1.val[1];
                        Red[i][j]=Scalar1.val[2];
                }
        }

        /*Implement Algorithms*/
        for(int i=0;i<Height;i++)
        {
                for(int j=0;j<Width;j++)
                {
                        Gray[i][j]=0.299*Red[i][j] + 0.587*Green[i][j] + 0.114*Blue[i][j];
                        if(Gray[i][j]<Threshold)
                        {
                                Red[i][j]=0;
                                Green[i][j]=0;
                                Blue[i][j]=0;
                        }
                        else
                        {
                                Red[i][j]=255;
                                Green[i][j]=255;
                                Blue[i][j]=255;
                        }
                }
        }

        /*Save Image RGB Values*/
        for(int i=0;i<Height;i++)
        {
                for(int j=0;j<Width;j++)
                {
                        Scalar1=CV_RGB(Red[i][j],Green[i][j],Blue[i][j]);
                        cvSet2D(Image1,i,j,Scalar1);
                }
        }


        cvNamedWindow("Bower Thresholding",1);
        cvShowImage("Bower Thresholding",Image1);
        cvNamedWindow("Bower",1);
        cvShowImage("Bower",Image2);
        cvWaitKey(0);
}


执行结果:


上面的程序使用了cvCloneImage()复制了一份原始图片,而RGB算法的使用上相较之下已经比imageData的方式简单许多了,而 imageData也因此被包在下一层做运算了,这边除了用到了前面所提到的cvGet2D()跟cvSet2D()做运算,还设计了灰级的转换,而对灰 级做一个门槛值非黑即白就是二值化的制作了跟前面那篇"GUI接口的制作-Trackbar制作"的cvThreshold()是同一个算法,而中间 /*Implement Algorithms*/的部分,就可以自由的存取RGB值了!

这里再提到几个重要的部分,这部分做存取RGB 值的操作,会有许多的问题及瓶颈,今天假设要存取的图片是1000*1300大小的维度,使用一般的二维数组存取RGB值一定会爆掉,因为RGB数组的声明是存在静态Stack空间的,对编译器而言,Stack空间是有限的,而在编译的一开始编译器就配置了Stack空间的大小,因此解决的方法,除了去编 译器的环境配置下调整Stack空间的大小,要不然就是要使用二维动态数组了,而且使用动态二维数组,也可以在不晓得图片大小的情况下实例二维数组,动态 数组属于Heap的空间,当Heap空间不够的时候会被分页替换,对Heap空间来讲,其实是没上限的,但在使用上Heap会比Stack慢,而 CvMat,IplImage其实就是一种Heap的实例之一.简而言之,数据结就是使用到Heap空间.

另一个部分是分页错误的问题, 今天假如上面的程序代码,宽在第一层for循环,高在第二层for循环,会严重的影响程序的效能,因为他中间做了更多次的分页替换,对for循环来讲,每 做一次就会错一次,对一个二维数组的存取来说,不该有这种情形发生,详细的说明可以去参考操作系统原理分页替换的部分.

cvCloneImage()
复制一份完整的IplImage数据结构图像及配置
cvCloneImage(IplImage数据结构)


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter