图像处理经典算法及OpenCV程序
更新时间:2024-01-14 00:14:01 阅读量: 教育文库 文档下载
- 图像处理十大经典算法推荐度:
- 相关推荐
基于opencv的use摄像头视频采集程序 ........................................................................... 1 基于opencv的两个摄像头数据采集.................................................................................. 3 能激发你用代码做视频的冲动程序 ................................................................................... 6 图像反转(就是把黑的变白,白的变黑)........................................................................11 图像格式的转换 ............................................................................................................. 12 从摄像头或者AVI文件中得到视频流,对视频流进行边缘检测....................................... 13 采用Canny算子进行边缘检测........................................................................................ 15 角点检测........................................................................................................................ 18 图像的旋转加缩放(效果很拽,用地球做就像谷歌地球似的) ....................................... 21 Log-Polar极坐标变换 ..................................................................................................... 22 对图像进行形态学操作(图像的开闭,腐蚀和膨胀运算) .............................................. 24 用不同的核进行图像的二维滤波..................................................................................... 27 图像域的填充................................................................................................................. 30 寻找轮廓实现视频流的运动目标检测(超推荐一下) ..................................................... 35 采用金字塔方法进行图像分割 ........................................................................................ 40 图像的亮度变换 ............................................................................................................. 43 单通道图像的直方图 ...................................................................................................... 46 计算和显示彩色图像的二维色调-饱和度图像 .................................................................. 48 图像的直方图均匀化 ...................................................................................................... 50 用Hongh变换检测线段 .................................................................................................. 52 利用Hough变换检测圆(是圆不是椭圆) ...................................................................... 57 距离变换........................................................................................................................ 59 椭圆曲线拟合................................................................................................................. 64 由点集序列或数组创建凸外形 ........................................................................................ 68 Delaunay三角形和Voronoi划分的迭代式构造 ................................................................ 71 利用背景建模检测运动物体(推荐).............................................................................. 78 运动模板检测(摄像头) ............................................................................................... 81 显示如何利用Camshift算法进行彩色目标的跟踪............................................................ 86
基于opencv的use摄像头视频采集程序
准备工作:你得把opencv库装到电脑上,并把各种头文件,源文件,lib库都连到vc上,然后设置一下系统环境变量,这里这方面就不说了,好像我前面的文章有说过,不懂也可百度一下。
建立一个基于WIN32控制台的工程CameraUSB,在新建一个c++元文件,写代码: #include \#include \#include \#include \
void callback(IplImage* image); int main() {
int ncams=cvcamGetCamerasCount( );//返回可以访问的摄像头数目 HWND MyWin;
// 设置系统属性
cvcamSetProperty(0, CVCAM_PROP_ENABLE, CVCAMTRUE); //选择第一个摄像头 //camera
cvcamSetProperty(0, CVCAM_PROP_RENDER, CVCAMTRUE); //We'll render stream
// 在本例中
// 假设创建一个窗口,并且窗口的ID是在变量 MyWin 中定义 // MyWin 是窗口 HWND 的类型
MyWin=(HWND)cvGetWindowHandle(\
cvcamSetProperty(0,CVCAM_PROP_WINDOW,&MyWin); // Selects a window for
//video rendering //回调函数将处理每一帧
cvcamSetProperty(0,CVCAM_PROP_CALLBACK,callback); cvcamInit( ); cvcamStart( );
// 现在程序开始工作 cvWaitKey(0); cvcamStop( ); cvcamExit( ); return 0; }
// 在图像中画兰色水平线
void callback(IplImage* image) {
IplImage* image1 = image; int i,j;
assert (image);
for(i=0; i
for(j=(image1->widthStep)*i; j<(image1->widthStep)*(i+1); j+=image1->nChannels) {
image1->imageData[j] = (char)255; image1->imageData[j+1] = 0;
image1->imageData[j+2] = 0; } } }
嘿嘿,就这么简单就完事了。 不懂可留言问
基于opencv的两个摄像头数据采集
实现功能:同时采集两路USB摄像头数据,并显示,具有图片保存功能(点击左键保存图片,并暂停视频;右键继续视频)。步骤就不说了,很简单,直接放代码了:
#include
#include
void StereoCallback(IplImage *frame1,IplImage *frame2);
void onMouse1(int Event,int x,int y,int flags,void *param); void onMouse2(int Event,int x,int y,int flags,void *param); IplImage *image1,*image2;
char *strleft[4]={\char
*strright[4]={\void main() {
HWND CaptureWindow1=0; //不赋值也行 HWND CaptureWindow2=0;
//int ncams=cvcamGetCamerasCount(); //获取摄像头的个数,在这里可有可无 //用对话框的形式来选取摄像头 int *CameraNumber;
int nSelected = cvcamSelectCamera(&CameraNumber); /* //灰色图像
image1=cvCreateImage(cvSize(320,240),IPL_DEPTH_8U,1);
image2=cvCreateImage(cvSize(320,240),IPL_DEPTH_8U,1); */
//彩色图像
image1=cvCreateImage(cvSize(320,240),IPL_DEPTH_8U,3); image2=cvCreateImage(cvSize(320,240),IPL_DEPTH_8U,3);
//初始化两个摄像头
cvNamedWindow(\
CaptureWindow1=(HWND)cvGetWindowHandle(\ cvcamSetProperty(CameraNumber[0], CVCAM_PROP_ENABLE, CVCAMTRUE);
cvcamSetProperty(CameraNumber[0], CVCAM_PROP_RENDER, CVCAMTRUE);
cvcamSetProperty(CameraNumber[0], CVCAM_PROP_WINDOW, &CaptureWindow1);
// cvSetMouseCallback(\
cvNamedWindow(\
CaptureWindow2=(HWND)cvGetWindowHandle(\ cvcamSetProperty(CameraNumber[1], CVCAM_PROP_ENABLE, CVCAMTRUE);
cvcamSetProperty(CameraNumber[1], CVCAM_PROP_RENDER, CVCAMTRUE);
cvcamSetProperty(CameraNumber[1], CVCAM_PROP_WINDOW, &CaptureWindow2);
// cvSetMouseCallback(\
//让两个摄像头同步
cvcamSetProperty(CameraNumber[0],CVCAM_STEREO_CALLBACK,(void*)&StereoCallback);
//启动程序
cvcamInit(); cvcamStart();
cvSetMouseCallback(\cvSetMouseCallback(\ cvWaitKey(0);
cvcamStop(); free(CameraNumber); cvcamExit();
cvDestroyWindow(\ cvDestroyWindow(\}
void StereoCallback(IplImage* frame1,IplImage *frame2) {
/* //把图像转换成灰度图并保存到image中 cvCvtColor(frame1,image1,CV_RGB2GRAY); cvCvtColor(frame2,image2,CV_RGB2GRAY); */
//拷贝图像到全局变量image中 该函数这样用存在问题 // cvCopy(frame1,image1); // cvCopy(frame2,image2); image1=cvCloneImage(frame1); image2=cvCloneImage(frame2); //对截取的图像翻转
cvFlip(image1,image1,0); cvFlip(image2,image2,0);
}
void onMouse1(int Event,int x,int y,int flags,void *param) {
static int num=0;
if(Event==CV_EVENT_LBUTTONDOWN) {
if(num==4)num=0;//只是固定定义了保存4张图片,为了不让程序非法而设置的复原
cvcamPause(); //图像保存
cvSaveImage(strleft[num],image1); // cvSaveImage(strright[num],image2); // cvSaveImage(\ // cvSaveImage(\ }
if(Event==CV_EVENT_RBUTTONDOWN) {
cvcamResume(); num++; } }
void onMouse2(int Event,int x,int y,int flags,void *param) {
static int num=0;
if(Event==CV_EVENT_LBUTTONDOWN) {
if(num==4)num=0;//只是固定定义了保存4张图片,为了不让程序非法而设置的复原
cvcamPause(); //图像保存
// cvSaveImage(strleft[num],image1); cvSaveImage(strright[num],image2); // cvSaveImage(\ // cvSaveImage(\ }
if(Event==CV_EVENT_RBUTTONDOWN) {
cvcamResume(); num++; } }
能激发你用代码做视频的冲动程序
这个程序是基于opencv的,连接库就不说了,直接建立一个基于win32的控制台程序,写代码就OK了。
/* 程序名:drawing..c
功能:展示OpenCV的图像绘制功能 */
#include \
#include \#include
char wndname[] = \
CvScalar random_color(CvRNG* rng) //函数 cvRNG 初始化随机数生成器并返回其状态,RNG 随机数生成器 {
int icolor = cvRandInt(rng); //函数 cvRandInt 返回均匀分布的随机 32-bit 无符号整型值并更新 RNG 状态
return CV_RGB(icolor&255, (icolor>>8)&255, (icolor>>16)&255); //
创建 一个色彩值 }
int main( int argc, char** argv ) {
int line_type = CV_AA; // change it to 8 to see non-antialiased graphics int i;
CvPoint pt1,pt2; //基于二维整形坐标轴的点 double angle;
CvSize sz; //矩形框大小,以像素为精度 CvPoint ptt[6]; CvPoint* pt[2]; int arr[2]; CvFont font; CvRNG rng;
int width = 1000, height = 700;
int width3 = width*3, height3 = height*3; CvSize text_size; int ymin = 0;
// Load the source image
IplImage* image = cvCreateImage( cvSize(width,height), 8, 3 ); IplImage* image2;
// Create a window
cvNamedWindow(wndname, 1 );
cvZero( image ); //#define cvZero cvSetZero void cvSetZero( CvArr* arr ); arr 要被清空数组
cvShowImage(wndname,image); rng = cvRNG((unsigned)-1); pt[0] = &(ptt[0]); pt[1] = &(ptt[3]); arr[0] = 3; arr[1] = 3;
for (i = 0; i< NUMBER; i++) {
pt1.x=cvRandInt(&rng) % width3 - width; pt1.y=cvRandInt(&rng) % height3 - height; pt2.x=cvRandInt(&rng) % width3 - width; pt2.y=cvRandInt(&rng) % height3 - height;
cvLine( image, pt1, pt2, random_color(&rng), cvRandInt(&rng), line_type, 0 );//绘制连接两个点的线段 cvShowImage(wndname,image); cvWaitKey(DELAY); }
for (i = 0; i< NUMBER; i++) {
pt1.x=cvRandInt(&rng) % width3 - width; pt1.y=cvRandInt(&rng) % height3 - height; pt2.x=cvRandInt(&rng) % width3 - width; pt2.y=cvRandInt(&rng) % height3 - height;
cvRectangle( image,pt1, pt2, random_color(&rng),
cvRandInt(&rng)-1, line_type, 0 );//绘制简单、指定粗细或者带填充的 矩形
cvShowImage(wndname,image); cvWaitKey(DELAY); }
for (i = 0; i< NUMBER; i++) {
pt1.x=cvRandInt(&rng) % width3 - width; pt1.y=cvRandInt(&rng) % height3 - height; sz.width =cvRandInt(&rng) 0; sz.height=cvRandInt(&rng) 0;
angle = (cvRandInt(&rng)00)*0.180;
cvEllipse( image, pt1, sz, angle, angle - 100, angle + 200, random_color(&rng), cvRandInt(&rng)-1, line_type, 0 );//函数cvEllipse用来绘制或者填充一个简单的椭圆弧或椭圆扇形 cvShowImage(wndname,image); cvWaitKey(DELAY); }
for (i = 0; i< NUMBER; i++) {
pt[0][0].x=cvRandInt(&rng) % width3 - width; pt[0][0].y=cvRandInt(&rng) % height3 - height; pt[0][1].x=cvRandInt(&rng) % width3 - width; pt[0][1].y=cvRandInt(&rng) % height3 - height; pt[0][2].x=cvRandInt(&rng) % width3 - width; pt[0][2].y=cvRandInt(&rng) % height3 - height; pt[1][0].x=cvRandInt(&rng) % width3 - width; pt[1][0].y=cvRandInt(&rng) % height3 - height;
pt[1][1].x=cvRandInt(&rng) % width3 - width; pt[1][1].y=cvRandInt(&rng) % height3 - height; pt[1][2].x=cvRandInt(&rng) % width3 - width; pt[1][2].y=cvRandInt(&rng) % height3 - height;
cvPolyLine( image, pt, arr, 2, 1, random_color(&rng),
cvRandInt(&rng), line_type, 0 );//函数cvPolyLine 绘制一个简单的或多样的多角曲线
cvShowImage(wndname,image); cvWaitKey(DELAY); }
for (i = 0; i< NUMBER; i++) {
pt[0][0].x=cvRandInt(&rng) % width3 - width; pt[0][0].y=cvRandInt(&rng) % height3 - height; pt[0][1].x=cvRandInt(&rng) % width3 - width; pt[0][1].y=cvRandInt(&rng) % height3 - height; pt[0][2].x=cvRandInt(&rng) % width3 - width; pt[0][2].y=cvRandInt(&rng) % height3 - height; pt[1][0].x=cvRandInt(&rng) % width3 - width; pt[1][0].y=cvRandInt(&rng) % height3 - height; pt[1][1].x=cvRandInt(&rng) % width3 - width; pt[1][1].y=cvRandInt(&rng) % height3 - height; pt[1][2].x=cvRandInt(&rng) % width3 - width; pt[1][2].y=cvRandInt(&rng) % height3 - height;
cvFillPoly( image, pt, arr, 2, random_color(&rng), line_type, 0 );//函数cvFillPoly用于一个单独被多变形轮廓所限定的区域内进行填充 cvShowImage(wndname,image); cvWaitKey(DELAY); }
for (i = 0; i< NUMBER; i++) {
pt1.x=cvRandInt(&rng) % width3 - width; pt1.y=cvRandInt(&rng) % height3 - height;
cvCircle( image, pt1, cvRandInt(&rng)00, random_color(&rng), cvRandInt(&rng)-1, line_type, 0 );//函数cvCircle绘制或填充一个给定圆心和半径的圆 cvShowImage(wndname,image); cvWaitKey(DELAY); }
for (i = 1; i< NUMBER; i++) {
pt1.x=cvRandInt(&rng) % width3 - width; pt1.y=cvRandInt(&rng) % height3 - height;
cvInitFont( &font, cvRandInt(&rng) % 8, (cvRandInt(&rng)0)*0.05+0.1, (cvRandInt(&rng)0)*0.05+0.1,
(cvRandInt(&rng)%5)*0.1, cvRound(cvRandInt(&rng)),
line_type );//字体结构初始化。函数 cvRound, cvFloor, cvCeil 用一种舍入方法将输入浮点数转换成整数。 cvRound 返回和参数最接近的整数值
cvPutText( image, \Petroleum University!\pt1, &font, random_color(&rng));//在图像中加入文本 cvShowImage(wndname,image); cvWaitKey(DELAY); }
cvInitFont( &font, CV_FONT_HERSHEY_COMPLEX, 3, 3, 0.0, 5, line_type );
cvGetTextSize( \设置字符串文本的宽度和高度
pt1.x = (width - text_size.width)/2; pt1.y = (height + text_size.height)/2; image2 = cvCloneImage(image);
for( i = 0; i < 255; i++ ) {
cvSubS( image2, cvScalarAll(i), image, 0 );//函数 cvSubS 从原数组的每个元素中减去一个数量
cvPutText( image, \CV_RGB(255,i,i));
cvShowImage(wndname,image); cvWaitKey(DELAY); }
// Wait for a key stroke; the same function arranges events processing cvWaitKey(0);
cvReleaseImage(&image); cvReleaseImage(&image2); cvDestroyWindow(wndname);
return 0; }
效果图:太帅了
图像反转(就是把黑的变白,白的变黑)
黑的变白了,白的变黑了 源码:
#include
#include
int main(int argc,char* argv[]) {
IplImage* img=0;
int height,width,step,channels; UCHAR* data; int i,j,k; if(argc<2) {
printf(\ exit(0); }
img=cvLoadImage(argv[1]); if(!img) {
printf(\ exit(0); }
height=img->height; width=img->width; step=img->widthStep;
channels=img->nChannels;
data=(UCHAR*)img->imageData;
printf(\channels\\n\
cvNamedWindow(\cvMoveWindow(\
for(i=0;i for(k=0;k data[i*step+j*channels+k]=255-data[i*step+j*channels+k]; cvShowImage(\cvWaitKey(0); cvReleaseImage(&img); return 0; } 图像格式的转换 首先要准备一张图片,和几个txt文档,把txt文档的扩展名改成一个你要把图片转换成的格式 我用的原始图片是jpg的,txt改成bmp的 使用时,运行-cmd-cd 转到你的目录- Convert.exe 1.jpg 2.bmp 运行就能把图像1.jpg转换成2.bmp了 源码如下: /* 程序名:convert.c 功能:图像格式的转换 */ #include #include int main( int argc, char** argv ) { IplImage* src; // -1: the loaded image will be loaded as is (with number of channels depends on the file). if(argc != 3) { printf(\JPG,BMP,TIF,PNG,PPM\\n\ printf(\ return 0; } if( ( strstr(argv[1],\&& strstr(argv[1],\ && strstr(argv[1],\&& strstr(argv[1],\&& strstr(argv[1],\ || ( strstr(argv[2],\&& strstr(argv[2],\&& strstr(argv[2],\&& strstr(argv[2],\ && strstr(argv[2],\的用法是不是在a数组内查看是否有b数组。。。没有则输出NULL { printf(\CONV only support JPG,BMP,TIF,PPM,TGA and PPM\\n\ } else { if( (src=cvLoadImage(argv[1], -1))!= 0 ) { cvSaveImage( argv[2], src); cvReleaseImage(&src); printf(\ } else { printf(\ } } return 0; } 发现了个小问题: 原来的jpg图像只有102KB转换成bmp后变成549KB ,在运行程序把这个bmp转成jpg又只有81KB。这真是汗死我了 从摄像头或者AVI文件中得到视频流,对视频流进行边缘检测 /* 程序名称:laplace.c 功能:从摄像头或者AVI文件中得到视频流,对视频流进行边缘检测,并输出结果。 */ #include \ #include \#include int main( int argc, char** argv ) { IplImage* laplace = 0; IplImage* colorlaplace = 0; IplImage* planes[3] = { 0, 0, 0 }; // 多个图像面 CvCapture* capture = 0; // 下面的语句说明在命令行执行程序时,如果指定AVI文件,那么处理从 // AVI文件读取的视频流,如果不指定输入变量,那么处理从摄像头获取 // 的视频流 if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 ); else if( argc == 2 ) capture = cvCaptureFromAVI( argv[1] ); if( !capture ) { fprintf(stderr,\ return -1; } cvNamedWindow( \// 循环捕捉,直到用户按键跳出循环体 for(;;) { IplImage* frame = 0; int i; frame = cvQueryFrame( capture ); if( !frame ) break; if( !laplace ) { for( i = 0; i < 3; i++ ) planes[i] = cvCreateImage( cvSize(frame->width,frame->height), 8, 1 ); laplace = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_16S, 1 ); colorlaplace = cvCreateImage( cvSize(frame->width,frame->height), 8, 3 ); } cvCvtPixToPlane( frame, planes[0], planes[1], planes[2], 0 ); for( i = 0; i < 3; i++ ) { cvLaplace( planes[i], laplace, 3 ); // 3: aperture_size cvConvertScaleAbs( laplace, planes[i], 1, 0 ); // planes[] = ABS(laplace) } cvCvtPlaneToPix( planes[0], planes[1], planes[2], 0, colorlaplace ); colorlaplace->origin = frame->origin; cvShowImage(\ if( cvWaitKey(10) >= 0 ) break; } cvReleaseCapture( &capture ); cvDestroyWindow(\ return 0; } 采用Canny算子进行边缘检测 #include \ #include \ char wndname[] = \ char tbarname[] = \int edge_thresh = 1; IplImage *image = 0, *cedge = 0, *gray = 0, *edge = 0; // 定义跟踪条的 callback 函数 void on_trackbar(int h) { cvSmooth( gray, edge, CV_BLUR, 3, 3, 0 ); cvNot( gray, edge ); // 对灰度图像进行边缘检测 cvCanny(gray, edge, (float)edge_thresh, (float)edge_thresh*3, 3); cvZero( cedge ); // copy edge points cvCopy( image, cedge, edge ); // 显示图像 cvShowImage(wndname, cedge); } int main( int argc, char** argv ) { char* filename = argc == 2 ? argv[1] : (char*)\ if( (image = cvLoadImage( filename, 1)) == 0 ) return -1; // Create the output image cedge = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 3); // 将彩色图像转换为灰度图像 gray = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 1); edge = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 1); cvCvtColor(image, gray, CV_BGR2GRAY); // Create a window cvNamedWindow(wndname, 1); // create a toolbar cvCreateTrackbar(tbarname, wndname, &edge_thresh, 100, on_trackbar); // Show the image on_trackbar(1); // Wait for a key stroke; the same function arranges events processing cvWaitKey(0); cvReleaseImage(&image); cvReleaseImage(&gray); cvReleaseImage(&edge); cvDestroyWindow(wndname); return 0; } /*******代码中的函数说明 1、cvSmooth,其函数声明为: cvSmooth( const void* srcarr, void* dstarr, int smoothtype,int param1, int param2, double param3 ) cvSmooth函数的作用是对图象做各种方法的图象平滑。其中,srcarr为输入图象;dstarr为输出图象; param1为平滑操作的第一个参数;param2为平滑操作的第二个参数(如果param2值为0,则表示它被设为param1); param3是对应高斯参数的标准差。 参数smoothtype是图象平滑的方法选择,主要的平滑方法有以下五种: CV_BLUR_NO_SCALE:简单不带尺度变换的模糊,即对每个象素在 param1×param2领域求和。 CV_BLUR:对每个象素在param1×param2邻域求和并做尺度变换 1/(param1?param2)。 CV_GAUSSIAN:对图像进行核大小为param1×param2的高斯卷积。 CV_MEDIAN:对图像进行核大小为param1×param1 的中值滤波(邻域必须是方的)。 CV_BILATERAL:双向滤波,应用双向 3x3 滤波,彩色设置为param1,空间设置为param2。 2、void cvNot(const CvArr* src,CvArr* dst); 函数cvNot()会将src中的每一个元素的每一位取反,然后把结果赋给dst。 因此,一个值为0x00的8位图像将被映射到0xff,而值为0x83的图像将被映射到0x7c。 3、void cvCanny( const CvArr* image, CvArr* edges, double threshold1,double threshold2, int aperture_size=3 ); 采用 Canny 算法做边缘检测 image 输入图像 edges 输出的边缘图像 threshold1 第一个阈值 threshold2 第二个阈值 aperture_size Sobel 算子内核大小 4、void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL ); 在使用这个函数之前,你必须用cvCreateImage()一类的函数先开一段内存,然后传递给dst。 cvCopy会把src中的数据复制到dst的内存中。 5、cvCreateTrackbar 创建trackbar并将它添加到指定的窗口。 int cvCreateTrackbar( const char* trackbar_name, const char* window_name, int* value, int count, CvTrackbarCallback on_change ); trackbar_name 被创建的trackbar名字。 window_name 窗口名字,这个窗口将为被创建trackbar的父对象。 value 整数指针,它的值将反映滑块的位置。这个变量指定创建时的滑块位置。 count 滑块位置的最大值。最小值一直是0。 on_change 每次滑块位置被改变的时候,被调用函数的指针。这个函数应该被声明为void Foo(int); 如果没有回调函数,这个值可以设为NULL。 函数cvCreateTrackbar用指定的名字和范围来创建trackbar(滑块或者范围控制),指定与trackbar位置同步的变量, 并且指定当trackbar位置被改变的时候调用的回调函数。被创建的trackbar显示在指定窗口的顶端。 */ 角点检测 原始图: 处理后图: 源代码: #include #include \#define max_corners 100 int main( int argc, char** argv ) { int cornerCount=max_corners; CvPoint2D32f corners[max_corners]; IplImage *srcImage = 0, *grayImage = 0, *corners1 = 0, *corners2 = 0; int i; CvScalar color = CV_RGB(255,0,0); char* filename = argc == 2 ? argv[1] : (char*)\注意相对路径 cvNamedWindow( \1 ); // create HighGUI window with name \ //Load the image to be processed srcImage = cvLoadImage(filename, 1); grayImage = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_8U, 1); //copy the source image to copy image after converting the format cvCvtColor(srcImage, grayImage, CV_BGR2GRAY); //create empty images of same size as the copied images corners1= cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_32F, 1); corners2= cvCreateImage(cvGetSize(srcImage),IPL_DEPTH_32F, 1); cvGoodFeaturesToTrack (grayImage, corners1, corners2, corners, &cornerCount, 0.05, 5, 0, 3, // block size 0, // not use harris 0.4 ); printf(\ // draw circles at each corner location in the gray image and //print out a list the corners if(cornerCount>0) { for (i=0; i cvCircle(srcImage, cvPoint((int)(corners[i].x), (int)(corners[i].y)), 6, color, 2, CV_AA, 0); } } cvShowImage( \ cvReleaseImage(&srcImage); cvReleaseImage(&grayImage); cvReleaseImage(&corners1); cvReleaseImage(&corners2); cvWaitKey(0); // wait for key. The function has return 0; } 友情链接一下,这是别人写的: http://hi.http://www.wodefanwen.com//xiaoduo170/blog/item/2816460175c8330779ec2c64.html 图像的旋转加缩放(效果很拽,用地球做就像谷歌地球似的) #include \ #include \#include \ int main( int argc, char** argv ) { IplImage* src; /* the first command line parameter must be image file name */ if( argc==2 && (src = cvLoadImage(argv[1], -1))!=0) { IplImage* dst = cvCloneImage( src ); int delta = 1; int angle = 0; int opt = 1; // 1: 旋转加缩放 // 0: 仅仅旋转 double factor; cvNamedWindow( \ cvShowImage( \ for(;;) { float m[6]; // Matrix m looks like: // // [ m0 m1 m2 ] ===> [ A11 A12 b1 ] // [ m3 m4 m5 ] [ A21 A22 b2 ] // CvMat M = cvMat( 2, 3, CV_32F, m ); int w = src->width; int h = src->height; if(opt) // 旋转加缩放 factor = (cos(angle*CV_PI/180.) + 1.05)*2; else // 仅仅旋转 factor = 1; m[0] = (float)(factor*cos(-angle*2*CV_PI/180.)); m[1] = (float)(factor*sin(-angle*2*CV_PI/180.)); m[3] = -m[1]; m[4] = m[0]; // 将旋转中心移至图像中间 m[2] = w*0.5f; m[5] = h*0.5f; // dst(x,y) = A * src(x,y) + b cvGetQuadrangleSubPix( src, dst, &M);//提取象素四边形,使用子象素精度 cvNamedWindow( \ cvShowImage( \ if( cvWaitKey(5) == 27 ) break; angle =(int) (angle + delta) % 360; } // for-loop } return 0; } Log-Polar极坐标变换 原始图: 效果图:(正变换) 反变换: 正反变换只是函数中一个参数的不同,具体看你所需要的应用。 cvLogPolar函数可以用来模拟人类的中央视觉(foveal vision),并可以用于物体跟踪方面的尺度及旋转不变模板的快速匹配。 源代码: #include #include int main(int argc, char** argv) { IplImage* src; if( argc == 2 && (src=cvLoadImage(argv[1],1)) != 0 ) { IplImage* dst = cvCreateImage( cvSize(256,256), 8, 3 ); IplImage* src2 = cvCreateImage( cvGetSize(src), 8, 3 ); cvLogPolar( src, dst, cvPoint2D32f(src->width/2,src->height/2), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS ); cvLogPolar( dst, src2, cvPoint2D32f(src->width/2,src->height/2), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS+CV_WARP_INVERSE_MAP ); cvNamedWindow( \ cvShowImage( \ cvNamedWindow( \ cvShowImage( \ cvWaitKey(); } return 0; } 对图像进行形态学操作(图像的开闭,腐蚀和膨胀运算) 效果图:(什么东东长这么丑啊,汗) #include #include IplConvKernel* element = 0; int element_shape = CV_SHAPE_RECT; //the address of variable which receives trackbar position update int max_iters = 10; int open_close_pos = 0; int erode_dilate_pos = 0; // callback function for open/close trackbar void OpenClose(int pos) { int n = open_close_pos - max_iters; int an = n > 0 ? n : -n; element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, element_shape, 0 ); if( n < 0 ) { cvErode(src,dst,element,1); cvDilate(dst,dst,element,1); } else { cvDilate(src,dst,element,1); cvErode(dst,dst,element,1); } cvReleaseStructuringElement(&element); cvShowImage(\} // callback function for erode/dilate trackbar void ErodeDilate(int pos) { int n = erode_dilate_pos - max_iters; int an = n > 0 ? n : -n; element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, element_shape, 0 ); if( n < 0 ) { cvErode(src,dst,element,1); } else { cvDilate(src,dst,element,1); } cvReleaseStructuringElement(&element); cvShowImage(\} int main( int argc, char** argv ) { char* filename = argc == 2 ? argv[1] : (char*)\ if( (src = cvLoadImage(filename,1)) == 0 ) return -1; printf( \ \ \ \ \ \ dst = cvCloneImage(src); //create windows for output images cvNamedWindow(\ cvNamedWindow(\ open_close_pos = erode_dilate_pos = max_iters; cvCreateTrackbar(\ \ cvCreateTrackbar(\ \ for(;;) { int c; OpenClose(open_close_pos); ErodeDilate(erode_dilate_pos); c = cvWaitKey(0); if( (char)c == 27 ) break; if( (char)c == 'e' ) element_shape = CV_SHAPE_ELLIPSE; else if( (char)c == 'r' ) element_shape = CV_SHAPE_RECT; else if( (char)c == 'c' ) element_shape = CV_SHAPE_CROSS; else if( (char)c == '\\n' ) element_shape = (element_shape + 1) % 3; } //release images cvReleaseImage(&src); cvReleaseImage(&dst); //destroy windows cvDestroyWindow(\ cvDestroyWindow(\ return 0; } 用不同的核进行图像的二维滤波 函数cvSmooth实现各种方法的图形平滑。 一般来说,图像平滑主要是为了消除噪声。图像的常见噪声主要有加性噪声、乘性噪声和量化噪声等。由于图像的能量主要集在低频部分,而噪声所在频段主要在高频段,因此通常都是采用低通滤波的方法消除噪声。 函数cvFilter2D对图像做卷积运算。 对图像进行线性滤波,支持替换方式操作。当核运算部份超出输入图像时,边界外面的像素值等于离它最近的图像像素值。 效果图: 源代码: // Filtering for Image with variaty filtering kernel // // CV_PREWITT_3x3_V A gradient filter (vertical Prewitt operator). // -1 0 1 // -1 0 1 // -1 0 1 // CV_PREWITT_3x3_H A gradient filter (horizontal Prewitt operator). // 1 1 1 // 0 0 0 // -1 -1 -1 // CV_SOBEL_3x3_V A gradient filter (vertical Sobel operator). // -1 0 1 // -2 0 2 // -1 0 1 // CV_SOBEL_3x3_H A gradient filter (horizontal Sobel operator). // 1 2 1 // 0 0 0 // -1 -2 -1 // CV_LAPLACIAN_3x3 A 3x3 Laplacian highpass filter. // -1 -1 -1 // -1 8 -1 // -1 -1 -1 // CV_LAPLACIAN_3x3 A 3x3 Laplacian highpass filter (another kernel) // This kernel is similar with function: cvLaplace with aperture_size=1 // 0 1 0 // 1 -4 1 // 0 1 0 注:直接用cvFilter2D得到的结果与用cvLaplace得到的结果 // 略有不同 // CV_LAPLACIAN_5x5 A 5x5 Laplacian highpass filter. // -1 -3 -4 -3 -1 // -3 0 6 0 -3 // -4 6 20 6 -4 // -3 0 6 0 -3 // -1 -3 -4 -3 -1 // CV_GAUSSIAN_3x3 A 3x3 Gaussian lowpass filter. // This filter uses the kernel A/16,where // 1 2 1 // A = 2 4 2 // 1 2 1 // These filter coefficients correspond to a 2-dimensional Gaussian // distribution with standard deviation 0.85. // // CV_GAUSSIAN_5x5 A 5x5 Gaussian lowpass filter. // This filter uses the kernel A/571,where // 2 7 12 7 2 // 7 31 52 31 7 // A = 12 52 127 52 12 // 7 31 52 31 7 // 2 7 12 7 2 #include #include int main( int argc, char** argv ) { IplImage *src = 0, *dst = 0, *dst2 = 0; /*float k[9] = { 0, 1, 0, 1,-4, 1, 0, 1, 0}; */ float k[9] = { 1.f/16, 2.f/16, 1.f/16, 2.f/16, 4.f/16, 2.f/16, 1.f/16, 2.f/16, 1.f/16}; // 这里高斯核滤波器归一化 CvMat Km; //cvInitMatHeader( &Km, 3, 3, CV_32FC1, k, CV_AUTOSTEP ); Km = cvMat( 3, 3, CV_32F, k ); // 0: force to gray image src = cvLoadImage(\ dst = cvCloneImage( src ); cvNamedWindow(\ cvShowImage(\ cvNamedWindow(\ cvFilter2D( src, dst, &Km, cvPoint(-1,-1)); cvShowImage(\ cvWaitKey(0); cvReleaseImage( &src ); cvReleaseImage( &dst ); return 0; } 图像域的填充 效果图: 源代码: #include \ #include \#include IplImage* color_img0; IplImage* mask; IplImage* color_img; IplImage* gray_img0 = NULL; IplImage* gray_img = NULL; int ffill_case = 1; int lo_diff = 20, up_diff = 20; int connectivity = 4; int is_color = 1; int is_mask = 0; int new_mask_val = 255; void on_mouse( int event, int x, int y, int flags, void* param ) { if( !color_img ) return; switch( event ) { case CV_EVENT_LBUTTONDOWN: { CvPoint seed = cvPoint(x,y); int lo = ffill_case == 0 ? 0 : lo_diff; int up = ffill_case == 0 ? 0 : up_diff; int flags = connectivity + (new_mask_val << 8) + (ffill_case == 1 ? CV_FLOODFILL_FIXED_RANGE : 0); int b = rand() & 255, g = rand() & 255, r = rand() & 255; CvConnectedComp comp; if( is_mask ) cvThreshold( mask, mask, 1, 128, CV_THRESH_BINARY ); if( is_color ) { CvScalar color = CV_RGB( r, g, b ); cvFloodFill( color_img, seed, color, CV_RGB( lo, lo, lo ), CV_RGB( up, up, up ), &comp, flags, is_mask ? mask : NULL ); cvShowImage( \ } else { CvScalar brightness = cvRealScalar((r*2 + g*7 + b + 5)/10); cvFloodFill( gray_img, seed, brightness, cvRealScalar(lo), cvRealScalar(up), &comp, flags, is_mask ? mask : NULL ); cvShowImage( \ } printf(\ if( is_mask ) cvShowImage( \ } break; } } int main( int argc, char** argv ) { char* filename = argc >= 2 ? argv[1] : (char*)\ if( (color_img0 = cvLoadImage(filename,1)) == 0 ) return 0; printf( \ \ \ \ \ \ \- use gradient floodfill with fixed(absolute) range\\n\ \range\\n\ \ \ color_img = cvCloneImage( color_img0 ); gray_img0 = cvCreateImage( cvSize(color_img->width, color_img->height), 8, 1 ); cvCvtColor( color_img, gray_img0, CV_BGR2GRAY ); gray_img = cvCloneImage( gray_img0 ); mask = cvCreateImage( cvSize(color_img->width + 2, color_img->height + 2), 8, 1 ); cvNamedWindow( \ cvCreateTrackbar( \ cvCreateTrackbar( \ cvSetMouseCallback( \ for(;;) { int c; if( is_color ) cvShowImage( \ else cvShowImage( \ c = cvWaitKey(0); switch( (char) c ) { case '\\x1b': printf(\ goto exit_main; case 'c': if( is_color ) { printf(\ cvCvtColor( color_img, gray_img, CV_BGR2GRAY ); is_color = 0; } else { printf(\ cvCopy( color_img0, color_img, NULL ); cvZero( mask ); is_color = 1; } break; case 'm': if( is_mask ) { cvDestroyWindow( \ is_mask = 0; } else { cvNamedWindow( \ cvZero( mask ); cvShowImage( \ is_mask = 1; } break; case 'r': printf(\ cvCopy( color_img0, color_img, NULL ); cvCopy( gray_img0, gray_img, NULL ); cvZero( mask ); break; case 's': printf(\ ffill_case = 0; break; case 'f': printf(\ ffill_case = 1; break; case 'g': printf(\(floating range) floodfill mode is set\\n\ ffill_case = 2; break; case '4': printf(\ connectivity = 4; break; case '8': printf(\ connectivity = 8; break; } } exit_main: cvDestroyWindow( \ cvReleaseImage( &gray_img ); cvReleaseImage( &gray_img0 ); cvReleaseImage( &color_img ); cvReleaseImage( &color_img0 ); cvReleaseImage( &mask ); return 1; } 寻找轮廓实现视频流的运动目标检测(超推荐一下) 效果视频我上传了,浏览网址(个人感觉很牛,有点像生化危机里的一个场景): http://tinypic.com/m/a2epo8/2 如果上面的卡,可以连这个,就是有点发散图形: http://i41.tinypic.com/54xcsm.jpg 也不说什么了,直接给代码吧(有一句话想说,实际上如果你是拿来做实际项目的,可能并不要学习里面的算法,直接利用里面的模板,也就是外接的调用函数就可以了): #include \ #include \#include #include // various tracking parameters (in seconds) const double MHI_DURATION = 0.5; const double MAX_TIME_DELTA = 0.5; const double MIN_TIME_DELTA = 0.05; const int N = 3; // const int CONTOUR_MAX_AERA = 16; // ring image buffer IplImage **buf = 0; int last = 0; // temporary images IplImage *mhi = 0; // MHI: motion history image CvFilter filter = CV_GAUSSIAN_5x5; CvConnectedComp *cur_comp, min_comp; CvConnectedComp comp; CvMemStorage *storage; CvPoint pt[4]; // 参数: // img – 输入视频帧 // dst – 检测结果 void update_mhi( IplImage* img, IplImage* dst, int diff_threshold ) { double timestamp = clock()/100.; // get current time in seconds CvSize size = cvSize(img->width,img->height); // get current frame size int i, j, idx1, idx2; IplImage* silh; uchar val; float temp; IplImage* pyr = cvCreateImage( cvSize((size.width & -2)/2, (size.height & -2)/2), 8, 1 ); CvMemStorage *stor; CvSeq *cont, *result, *squares; CvSeqReader reader; if( !mhi || mhi->width != size.width || mhi->height != size.height ) { if( buf == 0 ) { buf = (IplImage**)malloc(N*sizeof(buf[0])); memset( buf, 0, N*sizeof(buf[0])); } for( i = 0; i < N; i++ ) { cvReleaseImage( &buf[i] ); buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 ); cvZero( buf[i] ); } cvReleaseImage( &mhi ); mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 ); cvZero( mhi ); // clear MHI at the beginning } // end of if(mhi) cvCvtColor( img, buf[last], CV_BGR2GRAY ); // convert frame to grayscale idx1 = last; idx2 = (last + 1) % N; // index of (last - (N-1))th frame last = idx2; // 做帧差 silh = buf[idx2]; cvAbsDiff( buf[idx1], buf[idx2], silh ); // get difference between frames // 对差图像做二值化 cvThreshold( silh, silh, 30, 255, CV_THRESH_BINARY ); // and threshold it cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI cvCvtScale( mhi, dst, 255./MHI_DURATION, (MHI_DURATION - timestamp)*255./MHI_DURATION ); cvCvtScale( mhi, dst, 255./MHI_DURATION, 0 ); // 中值滤波,消除小的噪声 cvSmooth( dst, dst, CV_MEDIAN, 3, 0, 0, 0 ); // 向下采样,去掉噪声 cvPyrDown( dst, pyr, 7 ); cvDilate( pyr, pyr, 0, 1 ); // 做膨胀操作,消除目标的不连续空洞 cvPyrUp( pyr, dst, 7 ); // // 下面的程序段用来找到轮廓 // // Create dynamic structure and sequence. stor = cvCreateMemStorage(0); cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint) , stor); // 找到所有轮廓 cvFindContours( dst, stor, &cont, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0)); /* for(;cont;cont = cont->h_next) { // Number point must be more than or equal to 6 (for cvFitEllipse_32f). if( cont->total < 6 ) continue; // Draw current contour. cvDrawContours(img,cont,CV_RGB(255,0,0),CV_RGB(255,0,0),0,1, 8, cvPoint(0,0)); } // end of for-loop: \*/ // 直接使用CONTOUR中的矩形来画轮廓 for(;cont;cont = cont->h_next) { CvRect r = ((CvContour*)cont)->rect; if(r.height * r.width > CONTOUR_MAX_AERA) // 面积小的方形抛弃掉 { cvRectangle( img, cvPoint(r.x,r.y), cvPoint(r.x + r.width, r.y + r.height), CV_RGB(255,0,0), 1, CV_AA,0); } } // free memory cvReleaseMemStorage(&stor); cvReleaseImage( &pyr ); } int main(int argc, char** argv) { IplImage* motion = 0; CvCapture* capture = 0; //视频获取结构 if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) //原型:extern int isdigit(char c); //用法:#include capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 ); else if( argc == 2 ) capture = cvCaptureFromAVI( argv[1] ); if( capture ) { cvNamedWindow( \ for(;;) { IplImage* image; if( !cvGrabFrame( capture )) //从摄像头或者视频文件中抓取帧 break; image = cvRetrieveFrame( capture ); //取回由函数cvGrabFrame抓取的图像,返回由函数cvGrabFrame 抓取的图像的指针 if( image ) { if( !motion ) { motion = cvCreateImage( cvSize(image->width,image->height), 8, 1 ); cvZero( motion ); motion->origin = image->origin; ///* 0 - 顶—左结构, 1 - 底—左结构 (Windows bitmaps 风格) */ } } update_mhi( image, motion, 60 ); cvShowImage( \ if( cvWaitKey(10) >= 0 ) break; } cvReleaseCapture( &capture ); cvDestroyWindow( \ } return 0; } 采用金字塔方法进行图像分割 图像分割指的是将数字图像细分为多个图像子区域的过程,在OpenCv中实现了三种跟图像分割相关的算法,它们分别是:分水岭分割算法、金字塔分割算法以及均值漂移分割算法。 分水岭分割算法 分水岭分割算法需要您或者先前算法提供标记,该标记用于指定哪些大致区域是目标,哪些大致区域是背景等等;分水岭分割算法的分割效果严重依赖于提供的标记。OpenCv中的函数cvWatershed实现了该算法 金字塔分割算法 金字塔分割算法由cvPrySegmentation所实现,该函数的使用很简单;需要注意的是图像的尺寸以及金字塔的层数,图像的宽度和高度必须能被2整除,能够被2整除的次数决定了金字塔的最大层数 均值漂移分割算法 均值漂移分割算法由cvPryMeanShiftFiltering所实现,均值漂移分割的金字塔层数只能介于[1,7]之间 友情链接一下,个人感觉比较好的这方面博客: http://www.cnblogs.com/xrwang/archive/2010/02/28/ImageSegmentation.html 效果图: #include \ #include \#include IplImage* image[2] = { 0, 0 }, *image0 = 0, *image1 = 0; CvSize size; int w0, h0,i; int threshold1, threshold2; int l,level = 4; int sthreshold1, sthreshold2; int l_comp; int block_size = 1000; float parameter; double threshold; double rezult, min_rezult; CvFilter filter = CV_GAUSSIAN_5x5; CvConnectedComp *cur_comp, min_comp; CvSeq *comp; CvMemStorage *storage; CvPoint pt1, pt2; void ON_SEGMENT(int a) { cvPyrSegmentation(image0, image1, storage, &comp, level, threshold1+1, threshold2+1); /*l_comp = comp->total; i = 0; min_comp.value = cvScalarAll(0); while(i cur_comp = (CvConnectedComp*)cvGetSeqElem ( comp, i ); if(fabs(255- min_comp.value.val[0])> fabs(255- cur_comp->value.val[0]) && fabs(min_comp.value.val[1])> fabs(cur_comp->value.val[1]) && fabs(min_comp.value.val[2])> fabs(cur_comp->value.val[2]) ) min_comp = *cur_comp; i++; }*/ cvShowImage(\} int main( int argc, char** argv ) { char* filename = argc == 2 ? argv[1] : (char*)\ if( (image[0] = cvLoadImage( filename, 1)) == 0 ) return -1; cvNamedWindow(\ cvShowImage(\ cvNamedWindow(\ storage = cvCreateMemStorage ( block_size ); image[0]->width &= -(1< threshold1 =255; threshold2 =30; ON_SEGMENT(1); sthreshold1 = cvCreateTrackbar(\&threshold1, 255, ON_SEGMENT); sthreshold2 = cvCreateTrackbar(\&threshold2, 255, ON_SEGMENT); cvShowImage(\ cvWaitKey(0); cvDestroyWindow(\ cvDestroyWindow(\ cvReleaseMemStorage(&storage ); cvReleaseImage(&image[0]); cvReleaseImage(&image0); cvReleaseImage(&image1); return 0; } 图像的亮度变换 郁闷,以前用过MatLab,很长时间没用了,都不知道怎么使了,据说做这个效果很不错。 效果图: 源代码: #include \ #include \/* src and dst are grayscale, 8-bit images; Default input value: [low, high] = [0,1]; X-Direction [bottom, top] = [0,1]; Y-Direction gamma ; if adjust successfully, return 0, otherwise, return non-zero. */ int ImageAdjust(IplImage* src, IplImage* dst, double low, double high, // X方向:low and high are the intensities of src double bottom, double top, // Y方向:mapped to bottom and top of dst double gamma ) { if( low<0 && low>1 && high <0 && high>1&& bottom<0 && bottom>1 && top<0 && top>1 && low>high) return -1; double low2 = low*255; double high2 = high*255; double bottom2 = bottom*255; double top2 = top*255; double err_in = high2 - low2; double err_out = top2 - bottom2; int x,y; double val; // intensity transform for( y = 0; y < src->height; y++) { for (x = 0; x < src->width; x++) { val = ((uchar*)(src->imageData + src->widthStep*y))[x]; val = pow((val - low2)/err_in, gamma) * err_out + bottom2; if(val>255) val=255; if(val<0) val=0; // Make sure src is in the range [low,high] ((uchar*)(dst->imageData + dst->widthStep*y))[x] = (uchar) val; } } return 0; } int main( int argc, char** argv ) { IplImage *src = 0, *dst = 0; if( argc != 2 || (src=cvLoadImage(argv[1], 0)) == NULL) // force to gray image return -1; cvNamedWindow( \ cvNamedWindow( \ // Image adjust dst = cvCloneImage(src); // 输入参数 [0,0.5] 和 [0.5,1], gamma=1 if( ImageAdjust( src, dst, 0, 0.5, 0.5, 1, 1)!=0) return -1; cvShowImage( \ cvShowImage( \ cvWaitKey(0); cvDestroyWindow(\ cvDestroyWindow(\ cvReleaseImage( &src ); cvReleaseImage( &dst ); return 0; } 单通道图像的直方图 原始图: 效果图: 源代码: #include \ #include \#include int main( int argc, char** argv ) { IplImage *src = 0; IplImage *histimg = 0; CvHistogram *hist = 0; int hdims = 50; // 划分HIST的个数,越高越精确 float hranges_arr[] = {0,255}; float* hranges = hranges_arr; int bin_w; float max_val; int i; if( argc != 2 || (src=cvLoadImage(argv[1], 0)) == NULL) // force to gray image return -1; cvNamedWindow( \ cvNamedWindow( \ hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); // 计 算直方图 histimg = cvCreateImage( cvSize(320,200), 8, 3 ); cvZero( histimg ); cvCalcHist( &src, hist, 0, 0 ); // 计算直方图 cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 ); // 只找最大值 cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); // 缩放 bin 到区间 [0,255] cvZero( histimg ); bin_w = histimg->width / hdims; // hdims: 条的个数,则 bin_w 为条的宽度 // 画直方图 for( i = 0; i < hdims; i++ ) { double val = ( cvGetReal1D(hist->bins,i)*histimg->height/255 ); CvScalar color = CV_RGB(255,255,0); //(hsv2rgb(i*180.f/hdims); cvRectangle( histimg, cvPoint(i*bin_w,histimg->height), cvPoint((i+1)*bin_w,(int)(histimg->height - val)), color, 1, 8, 0 ); } cvShowImage( \ cvShowImage( \ cvWaitKey(0); cvDestroyWindow(\ cvDestroyWindow(\ cvReleaseImage( &src ); cvReleaseImage( &histimg ); cvReleaseHist ( &hist ); return 0; } 计算和显示彩色图像的二维色调-饱和度图像 对这篇内容很郁闷,不知道以后用来干什么,声明一下,哥不是搞图像处理的。(业余爱好) 效果图:(好好的一张图,给处理成人不像人,鬼不像鬼) #include #include int main( int argc, char** argv ) { IplImage* src; if( argc == 2 && (src=cvLoadImage(argv[1], 1))!= 0) { IplImage* h_plane = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* s_plane = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* v_plane = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* planes[] = { h_plane, s_plane }; IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 ); int h_bins = 30, s_bins = 32; int hist_size[] = {h_bins, s_bins}; float h_ranges[] = { 0, 180 }; /* hue varies from 0 (~0°red) to 180 (~360°red again) */ float s_ranges[] = { 0, 255 }; /* saturation varies from 0 (black-gray-white) to 255 (pure spectrum color) */ float* ranges[] = { h_ranges, s_ranges }; int scale = 10; IplImage* hist_img = cvCreateImage( cvSize(h_bins*scale,s_bins*scale), 8, 3 ); CvHistogram* hist; float max_value = 0; int h, s; cvCvtColor( src, hsv, CV_BGR2HSV ); cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 ); hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 ); cvCalcHist( planes, hist, 0, 0 ); cvGetMinMaxHistValue( hist, 0, &max_value, 0, 0 ); cvZero( hist_img ); for( h = 0; h < h_bins; h++ ) { for( s = 0; s < s_bins; s++ ) { float bin_val = cvQueryHistValue_2D( hist, h, s ); int intensity = cvRound(bin_val*255/max_value); cvRectangle( hist_img, cvPoint( h*scale, s*scale ), cvPoint( (h+1)*scale - 1, (s+1)*scale - 1), CV_RGB(intensity,intensity,intensity), CV_FILLED ); } } cvNamedWindow( \ cvShowImage( \ cvNamedWindow( \ cvShowImage( \ cvWaitKey(0); } } 图像的直方图均匀化 直方图均衡化算法可以归一化图像的亮度,并增强图像的对比度 效果图:
正在阅读:
图像处理经典算法及OpenCV程序01-14
企业集团公司组织架构模式比较03-29
农村中学英语学困生的成因及转化策略03-12
2022届高考地理一轮复习第四部分区域地理第十八章中国地理1中国04-20
技术与设计2期中考试题目及答案03-14
中考物理复习电学部分测试题05-12
中小学教师培训评估的发展趋势分析04-21
第一轮 等效平衡(无答案)04-28
2014年 五年级上数学复习计划09-11
《电视娱乐节目主持人个性化研究》06-28
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 图像处理
- 算法
- 程序
- 经典
- OpenCV
- 创建全国文明城市工作先进个人事迹材料
- 2018-2019年贵州省贵阳市质检一:贵阳市2018届高三第一次质量检测英语试题-附答案精品
- 甘肃省小额贷款公司管理办法(2015新规)
- 2018医学检验技术中级考试历年真题汇总合集
- 2016-2017学年度九年级数学第一学期期末测试题(2)
- 2018年(辽宁地区)聚焦中考数学总复习 单元自我测试:第三章 函数自我测试
- 数控加工中心刀库设计论文 - 本科论文
- 2015年矿井灾害预防与处理计划(2)
- 南京某恒温恒湿实验室空调系统设计任务书、计算书
- 浅谈山区高速隧道水消防系统突出问题及改进措施
- 《钢琴艺术赏析》网络学习期末考试
- 2014年版核心期刊目录
- 会计分录综合练习题(练习题及答案)
- 安保计划编制(空白) - 图文
- 初一英语期末复习 - 语法填空
- 测定黄芩中黄芩苷的定性和定量方法
- 财务会计作业解析
- 关于表彰2012-2013学年校级三好学生、优秀学生干部、单项积极分子的决定
- 江苏华电湿除支架上部结构模板支撑专项施工方案报审版本(高支模)
- (完整版)优秀毕业设计毕业论文 源码基于Java的图书馆管理系统毕业设