IplImage构造
int depth = IPL_DEPTH_8U;
int channels = 1; //黑白 1,RGB 3
IplImage *pImg = cvCreateImage(cvSize(Width,Height),depth,channels);
for (int row = Height -1 ; row >= 0; --row)
{
for (int col = 0; col < Width; ++col)
{
int pos = pImg->widthStep * row + col;//如果depth为IPL_DEPTH_16U int pos = pImg->widthStep * row + col*2;
pImg->imageData[pos] = dat;
}
}
IplImage结构体赋值
void InitIpl(IplImage &img,char* DibBuf,int width,int height,int depth,int nchannel)
{
img.nSize = sizeof(IplImage);
img.ID = 0;
img.alphaChannel =0;
img.depth = depth;
strcpy_s(img.colorModel,4,"RGB");
strcpy_s(img.channelSeq,4,"BGR");
img.dataOrder = 0;
img.origin = 0;
img.align = 4;
img.roi = NULL;
img.maskROI = NULL;
img.imageId = NULL;
img.tileInfo = NULL;
memset(img.BorderMode,4,0);
memset(img.BorderConst,4,0);
img.imageDataOrigin = 0;
img.width = width;
img.height = height;
img.nChannels = nchannel;
img.imageSize = img.width * img.height * img.nChannels;
img.widthStep = img.width * img.nChannels;
img.imageData = DibBuf;
}
读取图像
IplImage *pImg = cvLoadImage("D:\1.png",CV_LOAD_IMAGE_ANYCOLOR|CV_LOAD_IMAGE_ANYDEPTH);
第二个参数可以不写,默认是将图像以8位3通道载入。
CV_LOAD_IMAGE_GRAYSCALE代表以单通道载入
第二个参数iscolor
>0 强制以彩色(3通道)
=0 灰度
<0 取决于图像本身
弹窗显示
可以在app类initInstance创建对话框前调用函数,取代对话框。
IplImage* img=cvLoadImage("d:\1.jpg"); //将图像加载到内存中
cvNamedWindow("picWindow",CV_WINDOW_AUTOSIZE);
//窗口名为picWindow,第二个参数默认0,表示任意拉伸。CV_WINDOW_AUTOSIZE表示窗口大小是图像的大小,不能拉伸
cvShowImage("picWindow",img);
//使用创建的窗口显示图片
cvWaitKey(0);//使程序暂停,等待用户按下键盘,参数0代表一直等待,如果参数为正数x,代表等待x毫秒
cvReleaseImage(&img);//释放内存中的图像
cvDestroyWindow("picWindow");//销毁创建的窗口
ROI
cvSetImageROI(img,cvRect(x,y,width,height));
cvResetImageROI(img);
在 cvSetImageROI和cvCopy函数时,一定要注意图像的大小(或ROI大小),避免越界和图像大小不一。
保存图片
可以将img保存为任意格式图片,保存图片的目录必须存在
cvSaveImage("d:\x.png",img);
创建与销毁
IplImage* img = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,3);
cvReleaseImage(&img);
创建时,也可以使用cvGetSize(img)作为参数
IplImage* img = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
归零
cvZero(img);
设置颜色
cvSet(pImg, cvScalar(0x00,0xDB, 0x00));
翻转
cvFlip(img,img,0);
IplImage中的origin成员为0,代表上下翻转,1代表左右翻转。
复制
cvCopy(src, dst);//将src拷贝到dst中
IplImage* dst=cvCloneImage(img);//将img完整复制一份
获取尺寸
int cx=cvGetSize(img).width;
int cy=cvGetSize(img).height;
或者
int cx=img->width;
int cy=img->height;
调整大小
将src变为dst的大小,dst为缩放后的图像。
IplImage* dst = cvCreateImage(cvSize(200,60),src->depth,src->nChannels);
cvResize(src,dst);
cvReleaseImage(&dst);//放在函数最后(处理图像结束后)释放内存
裁剪
将src进行裁剪,裁剪后的图像为dst。
int x=0,y=0,width=200,height=200;
IplImage* dst = cvCreateImage(cvSize(width,height),src->depth,src->nChannels);
cvSetImageROI(src,cvRect(x,y,width,height));//设置感兴趣的区域,也就是用来操作的区域
cvCopy(src,dst);
分离通道
cvSplit(src,r,g,b,NULL);
将src的rgb分别放到三个通道图中,r,g,b三个IplImage都是单通道的
平滑处理
将src平滑处理后放到dst
cvSmooth(src,dst,CV_GAUSSIAN ,3,3);
第三个以后的参数都有默认值。
第三个参数可以是:
CV_BLUR_NO_SCALE (简单不带尺度变换的模糊) - 对每个象素的 param1×param2 领域求和。如果邻域大小是变化的,可以事先利用函数 cvIntegral 计算积分图像。
CV_BLUR 对每个象素param1×param2邻域 求和并做尺度变换 1/(param1.param2).
CV_GAUSSIAN对图像进行核大小为 param1×param2 的高斯卷积
CV_MEDIAN对图像进行核大小为param1×param1 的中值滤波(邻域是方的).
CV_BILATERAL (双向滤波) - 应用双向 3x3 滤波,彩色sigma=param1,空间 sigma=param2. 平滑操作的第一个参数.
融合
两个图象可以是任何象素类型,只要它们的类型相同。它们可以是单通道或是三通道,只要它们相符。必须有相同的象素类型。这些图象可以是不同的尺寸,但它们的ROI必须有相同的大小。
融合时候,以图像本身大小为基准,而不是以显示界面的大小为基准
IplImage *dst, *src;
dst存储合成后的图
int width =200,height =300; //设置ROI大小相同
cvSetImageROI(dst, cvRect(0,0,width,height));
cvSetImageROI(src, cvRect(0,0,width,height));
//前两个参数代表图像左上角位置
double alpha =0.5;
double beta =1;//设置为0和1可以让上面的图盖在底图上
double gamma=0;
cvAddWeighted(dst, alpha, src,beta,gamma,dst);
//运算是dst=dst*alpha+src*beta+gamma;
cvResetImageROI(dst); //因为ROI变小,所以重置回原来的大小
去白色融合
去掉src2的白色,融合图放在src3
IplImage* src3 = cvCreateImage(cvSize(width,height),src1->depth,src1->nChannels);
cvAnd(src1,src2,src3);
cvAndS(src,cvScalar(255,255,0),src3); //可以用指定颜色进行位与
调色
为图片增加红色(红通道加了100,如果是负数代表减少颜色),cvScalar可以有四个参数BGRA
cvAddS(img,cvScalar(0,0,100),img);
反色
for(int i=0;i != height; ++ i)
{
for(int j=0;j != width; ++ j)
{
for(int k=0;k != channels; ++ k)
{
data[i*step+j*channels+k]=255-data[i*step+j*channels+k];
}
}
}
边缘检测
IplImage* img=cvLoadImage("d:\1.jpg",CV_LOAD_IMAGE_GRAYSCALE); //灰度图像
IplImage* CannyImg=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);
cvCanny(img,CannyImg,50,150,3);//输出为CannyImg
遍历IplImage处理图像
将img中蓝色最大化
IplImage* img = cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,3);
cvCopy(src, img);
for(int y=0;y<img->height;y++)
{
uchar* ptr=(uchar*)(img->imageData+y*img->widthStep);//ptr指向一行的数据长度,也就是指向的内存大小为一行的内存大小
for(int x=0;x<img->width;x++)
{
ptr[3*x+0]=255;//0,1,2分别代表蓝绿红,3*x是因为这是3通道的图像
}
}
ptr指向的行内存排列应该是:
B G R B G R 。。。。。。。。。
3*0+0 3*1+1
替代ROI方式
使img的部分区域红色增加100
int x=10,y=10,width=400,height=400;//感兴趣区域
IplImage* sub_img=cvCreateImageHeader(cvSize(width,height),img->depth,img->nChannels);
sub_img->origin=img->origin;
sub_img->widthStep=img->widthStep;
sub_img->imageData=img->imageData + img->widthStep*y + img->nChannels*x;
cvAddS(sub_img,cvScalar(0,0,100),sub_img);//让红通道增加100
cvReleaseImageHeader(&sub_img);
ROI只能串行处理,且不断设置和重置,该方式可以保持一副图像的多个子区域处于活动状态下。
拉伸变换
不能对一幅图进行两次拉伸,需要多次拉伸时,用多个dst接收src的变换,然后设置ROI进行合成即可。
CvPoint2D32f srcTir[4],dstTir[4];
CvMat *warp_mat=cvCreateMat(3,3,CV_32FC1);
IplImage *src=cvLoadImage("d:\1.jpg");
IplImage *dst=cvCloneImage(src);
dst->origin=src->origin;
cvZero(dst);
///src中要进行变换的四个点坐标
srcTir[0].x=52;
srcTir[0].y=0;//LT
srcTir[1].x=src->width-52;
srcTir[1].y=0;//RT
srcTir[2].x=0;
srcTir[2].y=300;//LB
srcTir[3].x=src->width;
srcTir[3].y=300;//RB
//变换后的四个点坐标
dstTir[0].x=0;
dstTir[0].y=0;
dstTir[1].x=src->width;
dstTir[1].y=0;
dstTir[2].x=0;
dstTir[2].y=300;
dstTir[3].x=src->width;
dstTir[3].y=300;
cvGetPerspectiveTransform(srcTir,dstTir,warp_mat);
cvWarpPerspective(src,dst,warp_mat);
////对dst进行显示///////
cvReleaseImage(&dst);
cvReleaseMat(&warp_mat);
转换颜色类型
#pragma comment(lib,"opencv_objdetect248d")
#pragma comment(lib,"opencv_imgproc248d")
IplImage* gray = cvCreateImage(cvSize(img->width, img->height), 8, 1);
cvCvtColor(img, gray, CV_BGR2GRAY);