//学习OPENCV第5章,简单图像处理
#include<stdio.h>
#include<cv.h>
#include<highgui.h>
#include<stdio.h>
#include <opencv2/legacy/legacy.hpp>
void f(IplImage* src, IplImage* dst,int layer);
void sum_rgb(IplImage* src,IplImage* dst);
void sum_rgb1(IplImage* src,IplImage* dst);
int main(int argc, char** argv)
{
//-------------------------------------------------------------------
//图像金字塔分割
IplImage* src = cvLoadImage("D:\\AI_Proj\\OPENCV\\cameraman.tif");
if(!src)
{
printf("Couldn't seem to Open image, sorry\n");
return -1;
}
//分别按照金字塔2/4/6层分割
IplImage* dst2l = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
IplImage* dst4 = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
IplImage* dst6 = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
f(src,dst2l,2);
f(src,dst4,4);
f(src,dst6,6);
cvNamedWindow("PyrSegmentation2",1);
cvNamedWindow("PyrSegmentation4",1);
cvNamedWindow("PyrSegmentation6",1);
cvShowImage("PyrSegmentation2",dst2l);
cvShowImage("PyrSegmentation4",dst4);
cvShowImage("PyrSegmentation6",dst6);
while(1)
{
if(cvWaitKey(100) == 27)
break;
}
cvDestroyWindow("PyrSegmentation2");
cvDestroyWindow("PyrSegmentation4");
cvDestroyWindow("PyrSegmentation6");
cvReleaseImage(&src);
cvReleaseImage(&dst2l);
cvReleaseImage(&dst4);
cvReleaseImage(&dst6);
cvWaitKey();
//-------------------------------------------------------------------
//rgb分离:加权加法得到目的图像
IplImage* src1 = cvLoadImage("D:\\AI_Proj\\OPENCV\\dog.jpg");
IplImage* dst1 = cvCreateImage(cvGetSize(src1),src1->depth,1);
sum_rgb(src1,dst1);
cvNamedWindow("split_rgb",1);
cvShowImage("split_rgb",dst1);
while(1)
{
if((cvWaitKey(10)&0x7f) == 27)
break;
}
cvDestroyWindow("split_rgb");
cvReleaseImage(&src1);
cvReleaseImage(&dst1);
cvWaitKey();
//-------------------------------------------------------------------
//rgb分离:通过累加cvAcc得到目的图像
IplImage* src2 = cvLoadImage("D:\\AI_Proj\\OPENCV\\dog.jpg");
IplImage* dst2 = cvCreateImage(cvGetSize(src2),src2->depth,1);
sum_rgb1(src2,dst2);
cvNamedWindow("cvAcc_rgb",1);
cvShowImage("cvAcc_rgb",dst2);
while(1)
{
if((cvWaitKey(10)&0x7f) == 27)
break;
}
cvDestroyWindow("cvAcc_rgb");
cvReleaseImage(&src2);
cvReleaseImage(&dst2);
cvWaitKey();
//-------------------------------------------------------------------
//自适应分割:增加可配性
IplImage* Igray;
IplImage* It;
IplImage* Iat;
if(!(Igray = cvLoadImage("D:\\AI_Proj\\OPENCV\\dog.jpg",CV_LOAD_IMAGE_GRAYSCALE)))
return -1;
double threshold = 100;//(double)atof(argv[1]);
int threshold_type = CV_THRESH_BINARY;//atoi(argv[2]) ? CV_THRESH_BINARY : CV_THRESH_BINARY_INV;
int adaptive_method = CV_ADAPTIVE_THRESH_MEAN_C;//atoi(argv[3]) ? CV_ADAPTIVE_THRESH_MEAN_C : CV_ADAPTIVE_THRESH_GAUSSIAN_C;
int block_size = 3;//atoi(argv[4]);
double offset = 0;//(double)atof(argv[5]);
//Create the grayscale output images
It = cvCreateImage(cvSize(Igray->width,Igray->height),IPL_DEPTH_8U,1);
Iat = cvCreateImage(cvSize(Igray->width,Igray->height),IPL_DEPTH_8U,1);
//Threshold
cvThreshold(Igray,It,threshold,255,threshold_type);
//根据block_size内像素,二值化
//P159:只能处理8位图像,或浮点图像,源图像与目的图像不能一致。
cvAdaptiveThreshold(Igray,Iat,255,adaptive_method,threshold_type,block_size,offset);
//PUT UP 2 WINDOWS
cvNamedWindow("Raw",1);
cvNamedWindow("Threshold",1);
cvNamedWindow("Adaptive_Threshold",1);
//Show the results
cvShowImage("Raw",Igray);
cvShowImage("Threshold",It);
cvShowImage("Adaptive_Threshold",Iat);
cvWaitKey(0);
//Clean up
cvReleaseImage(&Igray);
cvReleaseImage(&It);
cvReleaseImage(&Iat);
cvDestroyWindow("Raw");
cvDestroyWindow("Threshold");
cvDestroyWindow("Adaptive_Threshold");
return(0);
}
//图像金字塔实现分割
void f(IplImage* src,IplImage* dst,int layer)
{
//为结构体CvMemStorage分配空间,返回指向该空间的指针
CvMemStorage* storage = cvCreateMemStorage(0);
//动态结构序列CvSeq是所有OpenCv动态数据结构的基础;有两种类型的序列:稠密序列,稀疏序列
CvSeq* comp = NULL;
//用金字塔实现图像分割P153
//http://blog.csdn.net/cartoonface/article/details/5998543
//参数:源/目的图像;存储连通部件的序列结果;分割部件的输出序列指针;
//最大层数layer;阈值200,50
cvPyrSegmentation(src,dst,storage,&comp,layer,200,50);
int n_comp = comp->total;
//对序列进行索引,或进行其他操作
for(int i=0;i<n_comp;i++)
{
//cvGetSeqElem返回索引指定元素的指针
//comp是要检测的序列,而i是元素在序列中的索引
CvConnectedComp* cc = (CvConnectedComp*) cvGetSeqElem(comp,i);
// do_something_with( cc );
}
cvReleaseMemStorage(&storage);
}
void sum_rgb(IplImage* src,IplImage* dst)
{
IplImage* r = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* g = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* b = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
//Temporary storage.
IplImage* s = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
//Split image onto the color planes.图像通道分离
cvSplit(src,r,g,b,NULL);
//Add equally weighted rgb values.
//s=r*1/3+g*1/3
//s=s*2/3+b*1/3
//通常不对8位数组进行加法运算,可能溢出。
//通过加权加法对3通道进行运算,高于100进行截断
cvAddWeighted(r,1./3.,g,1./3.,0.0,s);
cvAddWeighted(s,2./3.,b,1./3.,0.0,s);
//对value大于100的像素进行截断为255,不足100的保留原值
cvThreshold(s,dst,100,255,CV_THRESH_TRUNC);
cvNamedWindow("split_r",CV_WINDOW_AUTOSIZE);
cvNamedWindow("split_g",CV_WINDOW_AUTOSIZE);
cvNamedWindow("split_b",CV_WINDOW_AUTOSIZE);
cvNamedWindow("s",CV_WINDOW_AUTOSIZE);
cvShowImage("split_r",r);
cvShowImage("split_g",g);
cvShowImage("split_b",b);
cvShowImage("s",s);
cvWaitKey();
cvReleaseImage(&r);
cvReleaseImage(&g);
cvReleaseImage(&b);
cvReleaseImage(&s);
cvDestroyWindow("split_r");
cvDestroyWindow("split_g");
cvDestroyWindow("split_b");
cvDestroyWindow("s");
}
void sum_rgb1(IplImage* src,IplImage* dst)
{
IplImage* r = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* g = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* b = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* s = cvCreateImage(cvGetSize(src),IPL_DEPTH_32F,1);
cvSplit(src,r,g,b,NULL);
//图像累加
cvZero(s);
cvAcc(b,s);
cvAcc(g,s);
cvAcc(r,s);
cvThreshold(s,s,100,255,CV_THRESH_TRUNC );
//使用线性变换转换数组
//源/目的图像;缩放因子;添加的值
cvConvertScale(s,dst,1,0);
cvReleaseImage(&r);
cvReleaseImage(&g);
cvReleaseImage(&b);
cvReleaseImage(&s);
}
示例效果:
金字塔层数越多分割越模糊