这里就介绍算法实例让程序代码最简洁的的方式啦,跟前面直接存取不同,这边是用到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数据结构)