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资料结构)

posted on 2013-03-24 12:56  suwen  阅读(243)  评论(0编辑  收藏  举报

导航