OpenCV第五章练习p163_5~8
p163_5和p163_6代码如下:
#include <opencv/cv.h> #include <opencv/highgui.h> /********************************************** // 函数cvCount:统计二值图像image中像素值为value的数量 **********************************************/ int cvCount(IplImage *image, uchar value) { if(image == NULL || image->nChannels != 1) return 0; int cnt = 0; uchar *ptr = (uchar *)image->imageData; // 遍历图像中给定像素值的像素点的个数 for(int i = 0; i<image->height; i++) for(int j = 0; j<image->width; j++) if( *(ptr + i*image->widthStep + j) == value) cnt++; return cnt; } int main(int argc, char *argv[]) { char src_1[] = "src1.bmp"; char src_2[] = "src2.bmp"; IplImage *src1 = cvLoadImage(src_1, CV_LOAD_IMAGE_GRAYSCALE); IplImage *src2 = cvLoadImage(src_2, CV_LOAD_IMAGE_GRAYSCALE); if(!src1 || !src2){ cvNamedWindow("ERROR", CV_WINDOW_AUTOSIZE); cvWaitKey(0); return 0; } IplImage *diff12 = cvCreateImage(cvGetSize(src1), src1->depth, src1->nChannels); cvSub(src2, src1, diff12, NULL); cvAbs(diff12, diff12); cvThreshold(diff12, diff12, 40, 255, CV_THRESH_BINARY);// 超多阀值的设为255; cvNamedWindow("p163_5_1", 0); cvShowImage("p163_5_1", diff12); IplImage *temp = cvCreateImage(cvGetSize(diff12), diff12->depth, 1); temp->origin = diff12->origin; cvMorphologyEx(diff12, diff12, temp, NULL, CV_MOP_OPEN, 1); uchar *ptr = (uchar *)diff12->imageData; int i, j; int oldcnt = 0;int newcnt = 0; // 用于保存新旧区域像素的数量(即面积) CvPoint oldpos = cvPoint(0, 0); // 记录旧的连通区域的起始位置 for(i = 0; i<diff12->height; i++) for(j = 0; j<diff12->width; j++) if(255 == *(ptr+i*diff12->widthStep+j)){ cvFloodFill(diff12, cvPoint(j, i), cvScalar(100)); // 漫水填充为100,因为是单通道,不必cvScalar(100,100,100) newcnt = cvCount(diff12,100) - oldcnt; if(oldcnt < newcnt){ cvFloodFill(diff12, oldpos, cvScalar(0)); // 旧区域填充为0 oldcnt = newcnt; // 更新连通区域面积 oldpos = cvPoint(j, i); // 记录连通区域的位置 } else cvFloodFill(diff12, cvPoint(j, i), cvScalar(0));// 填充0 } cvFloodFill(diff12, oldpos, cvScalar(255));// 将最大的连通区域填充为255 cvSaveImage("fill.bmp", diff12, 0); cvNamedWindow("p163_5", 0); cvShowImage("p163_5", diff12); cvWaitKey(0); cvReleaseImage(&src1); cvReleaseImage(&src2); cvReleaseImage(&diff12); cvDestroyWindow("p163_5"); return 1; }
p163_7代码:
#include <opencv/cv.h> #include <opencv/highgui.h> int main(int argc, char *argv[]) { char src[] = "fill.bmp"; char src2[] = "src2.bmp"; IplImage *module = cvLoadImage(src, CV_LOAD_IMAGE_GRAYSCALE); IplImage *img = cvLoadImage(src2, CV_LOAD_IMAGE_COLOR); if(!module || !img){ cvNamedWindow("ERROR", CV_WINDOW_AUTOSIZE); cvWaitKey(0); return 0; } IplImage *cup = cvCreateImage(cvGetSize(img), img->depth, img->nChannels); cvCopy(img, cup, module); cvNamedWindow("p126_7", 0); cvShowImage("p126_7", cup); cvWaitKey(0); cvReleaseImage(&module); cvReleaseImage(&img); cvReleaseImage(&cup); cvDestroyWindow("p126_7"); return 1; }
p163_8
#include <opencv/cv.h> #include <opencv/highgui.h> // 生成一个有较小方差的随机图像 int main(int argc, char *argv[]) { IplImage *img = cvCreateImage(cvSize(320,480), IPL_DEPTH_8U, 1); CvRNG rng = cvRNG(cvGetTickCount()); uchar *ptr = (uchar *)img->imageData; for(int i = 0; i<img->height; i++) for(int j = 0; j<img->width; j++) *(ptr + i*img->widthStep + j) = cvRandInt(&rng) % 255; // 为求得明显效果,这里为0~255之间的随机数(题目中为3) cvNamedWindow("p163_8", 0); cvShowImage("p163_8", img); cvWaitKey(0); return 1; } /* int main(int argc, char *argv[]) { CvRNG rng = cvRNG(cvGetTickCount()); printf("%d%d", int(rng/65536),int(rng%65536)); for(int i=0; i<10; i++){ printf("%d\n", cvRandInt(&rng)%100); printf("%.2f\n", cvRandReal(&rng)); } return 1; } */
解释:
cvRNG()返回一个CvRNG结构,cvRandInt和cvRandReal使用。使用时赋给它一个64位长整数种子。而如果使用相同的种子,每次程序运行,后面的函数会出现一样的随机数。所以,将 cvGetTickCount返回系统时间计数值来得到种子,防止随机数重复。
http://blog.sina.com.cn/s/blog_79496d6b0100wjp5.html
cvRandInt()返回均匀分布32位的随机数,均匀分布为统计学上的专有名词,表示长时间下所有数字出现的概率都是一样的,而cvRandint()在opencv里使用的公式
temp = (uint64)(unsigned)temp*1554115554 + (temp >> 32);
这个公式的名称叫Multiply-with-carry (MWC) generator,有兴趣的话可以在网络上找“随机数产生器”,Multiply-with-carry是将64位的种子去产生32位的随机数。
unsigned cvRandInt(CvRNG资料结构)
cvRandReal()返回均匀分布,0~1之间的随机小数,cvRandReal()的公式则是用
cvRandInt(rng)*2.3283064365386962890625e-10
的方法,其实就是cvRandInt(rng)*2^(-32),也就是将cvRandInt()随机出来的结果(32位除以2的三十二次方,因此,出现的结果将会是0~1之间的小数,也就是随机0~1之间。
double cvRandReal(CvRNG资料结构)