使用OpenCV时需要了解的关键细节是图像数据结构是如何实现的。因此,要把OpenCV库和AIPCV连接起来的主要工作就在于提供一种在两种系统之间转换图像数据结构的方法。AIPCV库中的基本图像数据结构由两个数据结构组成:一个表示头信息,另一个表示图像。
struct header {
int nr, nc; /* Rows and columns in the image */
int oi, oj; /* Origin */
};
struct image {
struct header *info; /* Pointer to header */
unsigned char **data; /* Pixel values */
};
现在将AIPCV图像转换为OpenCV图像的方法很清晰明了,而且需要这种方法才能让图像显示在窗口中并且保存为JPEG和其他形式。(IMAGE----àIplImage)
IplImage *toOpenCV (IMAGE x)
{
IplImage *img;
unsigned char *z;
int i=0;
z = x->data[0];
//变量data[0]指向整个数组起始位置的指针,因而等同于IplImage.imageData
img = cvCreateImage (cvSize(x->info->nc, x->info->nr), IPL_DEPTH_8U, 1);
if (img)
for (i=0; i<x->info->nc*x->info->nr; i++)
img->imageData[i] = *z++;
return img;
}
IplImage转化为AIPCV更为复杂,因为OpenCV的图像可能是彩色的。如果是彩色的,那么如何才能转换为灰阶呢?一个彩色图像可以转换为3个单色图像(一个红色图像、一个绿色图像、一个蓝色图像),还可以构建一个使用单字节索引的色彩映射表,这个索引可以用作像素值。下面展示的解决方案将3通道彩色图像转换为灰阶图像,使用的方法是计算RGB值的平均值。(IplImage----àIMAGE)
IMAGE fromOpenCV (IplImage *x)
{
IMAGE img;
unsigned char *z, *y;
int color=0, i=0;
unsigned char k=0;
if ((x->depth==IPL_DEPTH_8U) &&(x->nChannels==1)) // 1 Pixel (grey) image
img = newimage (x->height, x->width);
else if ((x->depth==8) && (x->nChannels==3)) //Color
{
color = 1;
img = newimage (x->height, x->width);
}
else return 0;
z = (unsigned char *)(x->imageData);
y = img->data[0];
for (i=0; i<x->height*x->width; i++)
{
if (color) k = ((*z++) + (*z++) + (*z++))/3;
else k = *z++;
*(y++) = k;
}
return img;
}
例子:用Otsu设计的灰阶直方图方法进行阈值分割,
// thresh.c : Threshold an image. Use OpenCV AND AIPCV
//#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
#include <malloc.h>
#include <fcntl.h>
#include <io.h>
/* The image header data structure */
struct header {
int nr, nc; /* Rows and columns in the image */
int oi, oj; /* Origin */
};
/* The IMAGE data structure */
struct image {
struct header *info; /* Pointer to header */
unsigned char **data; /* Pixel values */
};
typedef struct image * IMAGE;
IMAGE newimage (int nr, int nc)
{
struct image *x; /* New image */
int i;
if (nr < 0 || nc < 0) {
printf ("Error: Bad image size (%d,%d)\n", nr, nc);
return 0;
}
/* Allocate the image structure */
x = (struct image *) malloc( sizeof (struct image) );
if (!x)
{
printf ("Out of storage in NEWIMAGE.\n");
return 0;
}
/* Allocate and initialize the header */
x->info = (struct header *)malloc( sizeof(struct header) );
if (!(x->info))
{
printf ("Out of storage in NEWIMAGE.\n");
return 0;
}
x->info->nr = nr; x->info->nc = nc;
x->info->oi = x->info->oj = 0;
/* Allocate the pixel array */
x->data = (unsigned char **)malloc(sizeof(unsigned char *)*nr);
/* Pointers to rows */
if (!(x->data))
{
printf ("Out of storage in NEWIMAGE.\n");
return 0;
}
x->data[0] = (unsigned char *)malloc (nr*nc);
if (x->data[0]==0)
{
printf ("Out of storage. Newimage.\n");
exit(1);
}
for (i=1; i<nr; i++)
{
x->data[i] = (x->data[0]+nr*i);
}
return x;
}
void freeimage (struct image *z)
{
/* Free the storage associated with the image Z */
if (z != 0)
{
free (z->info);
free (z->data);
free (z);
}
}
/* Otsu's method of 'grey level histograms' */
float nu (float *p, int k, float ut, float vt);
float u (float *p, int k);
void thr_glh (IMAGE im);
void thr_glh (IMAGE x)
{
/* Threshold selection using grey level histograms. SMC-9 No 1 Jan 1979
N. Otsu */
int i,j,k,n,m, h[260], t;
float y, z, p[260];
unsigned char *pp;
float ut, vt;
n = x->info->nr*x->info->nc;
for (i=0; i<260; i++) { /* Zero the histograms */
h[i] = 0;
p[i] = 0.0;
}
/* 累计直方图 */
for (i=0; i<x->info->nr; i++)
for (j=0; j<x->info->nc; j++) {
k = x->data[i][j];
h[k+1] += 1;
}
for (i=1; i<=256; i++) /*均一化 */
p[i] = (float)h[i]/(float)n;
ut = u(p, 256); /* Global mean */
vt = 0.0; /* Global Variance */
for (i=1; i<=256; i++)
vt += (i-ut)*(i-ut)*p[i];
j = -1; k = -1;
for (i=1; i<=256; i++) {
if ((j<0) && (p[i] > 0.0)) j = i; /* First index */
if (p[i] > 0.0) k = i; /* Last index */
}
z = -1.0;
m = -1;
for (i=j; i<=k; i++) {
y = nu (p, i, ut, vt); /* Compute NU */
if (y>=z) { /* Is it the biggest? */
z = y; /* Yes. Save value and i */
m = i;
}
}
t = m;
printf("Threshold found is %d\n", t);
/* Threshold */
pp = x->data[0];
for (i=0; i<n; i++)
if (*pp < t)
*pp++ = 0;
else
*pp++ = 255;
}
float w (float *p, int k)
{
int i;
float x=0.0;
for (i=1; i<=k; i++) x += p[i];
return x;
}
float u (float *p, int k)
{
int i;
float x=0.0;
for (i=1; i<=k; i++) x += (float)i*p[i];
return x;
}
float nu (float *p, int k, float ut, float vt)
{
float x, y;
y = w(p,k);
x = ut*y - u(p,k);
x = x*x;
y = y*(1.0F-y);
if (y>0) x = x/y;
else x = 0.0;
return x/vt;
}
IplImage *toOpenCV (IMAGE x)
{
IplImage *img;
unsigned char *z;
int i=0;
z = x->data[0];
img = cvCreateImage (cvSize(x->info->nc, x->info->nr), IPL_DEPTH_8U, 1);
if (img)
for (i=0; i<x->info->nc*x->info->nr; i++)
img->imageData[i] = *z++;
return img;
}
IMAGE fromOpenCV (IplImage *x)
{
IMAGE img;
unsigned char *z, *y;
int color=0, i=0;
unsigned char k=0;
if ((x->depth==IPL_DEPTH_8U) &&(x->nChannels==1)) // 1 Pixel (grey) image
img = newimage (x->height, x->width);
else if ((x->depth==8) && (x->nChannels==3)) //Color
{
color = 1;
img = newimage (x->height, x->width);
}
else return 0;
z = (unsigned char *)(x->imageData);
y = img->data[0];
for (i=0; i<x->height*x->width; i++)
{
if (color) k = ((*z++) + (*z++) + (*z++))/3;
else k = *z++;
*(y++) = k;
}
return img;
}
int main(int argc, char *argv[])
{
IplImage* img=0;
IplImage* img2=0;
IMAGE x;
int height,width,step,channels;
uchar *data;
int mean=0,count=0;
if(argc<1){
printf("Usage: main <image-file-name>\n\7");
exit(0);
}
// load an image
img=cvLoadImage("E:/image/Lina.bmp");
if(!img){
printf("Could not load image file: %s\n",argv[1]);
exit(0);
}
// get the image data
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
data = (uchar *)img->imageData;
printf("Processing a %dx%d image with %d channels\n",height,width,channels);
// create a window
cvNamedWindow("win1", CV_WINDOW_AUTOSIZE);
cvMoveWindow("win1", 100, 100);
// show the image
cvShowImage("win1", img );
// Convert to AIPCV IMAGE type
x = fromOpenCV (img);
if (x)
{
thr_glh (x);
img2 = toOpenCV (x);
cvNamedWindow( "thresh");
cvShowImage( "thresh", img2 );
cvSaveImage( "thresholded.jpg", img2 );
}
// wait for a key
cvWaitKey(0);
// release the image
cvReleaseImage(&img );
return 0;
}
结果如下: