OpenCV 之ios 随机数发生器&绘制文字

1.目的

本节你将学到:

  • 使用 随机数发生器类 (RNG) 并得到均匀分布的随机数。
  • 通过使用函数 putText 显示文字。

2代码

#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
#import <opencv2/imgproc.hpp>
#import <opencv2/highgui.hpp>
#import <opencv2/core/operations.hpp>

#import <opencv2/core/core_c.h>
using namespace cv;
using namespace std;

#endif
const int NUMBER = 100;
float window_height =900;
float window_width =600;
int x_1 = -window_width/2;
int x_2 = window_width*3/2;
int y_1 = -window_width/2;
int y_2 = window_width*3/2;

#import "RandomAndTextViewController.h"

@interface RandomAndTextViewController ()

@end
@implementation RandomAndTextViewController

RNG rng( 0xFFFFFFFF);
- (void)viewDidLoad {
    [super viewDidLoad];

    Mat image = Mat::zeros( window_height, window_width, CV_8UC3);
    UIImageView *imageView;
    [self Drawing_Random_Lines:image];
    [self Drawing_Random_Rectangles:image];
    [self Drawing_Random_Ellipses:image];
    [self Drawing_Random_Polylines:image];
    [self Drawing_Random_Filled_Polygons:image];
    [self Drawing_Random_Circles:image];
    [self Displaying_Random_Text:image];
    imageView = [self createImageViewInRect:self.view.bounds];
    [self.view addSubview:imageView];
    imageView.image  = [self UIImageFromCVMat:image];

//    [self Displaying_Big_End:image];


}
-(void)Drawing_Random_Lines:(Mat)image{
    cv::Point pt1, pt2;

     for( int i = 0; i < NUMBER; i++ )
     {
       pt1.x = rng.uniform( x_1, x_2 );
       pt1.y = rng.uniform( y_1, y_2 );
       pt2.x = rng.uniform( x_1, x_2 );
       pt2.y = rng.uniform( y_1, y_2 );

       line(image, pt1, pt2, [self randomColor], rng.uniform(1, 10), 8 );
     }
}
-(void)Drawing_Random_Rectangles:(Mat)image{
    cv::Point pt1, pt2;
     int lineType = 8;
     int thickness = rng.uniform( -3, 10 );

     for( int i = 0; i < NUMBER; i++ )
     {
       pt1.x = rng.uniform( x_1, x_2 );
       pt1.y = rng.uniform( y_1, y_2 );
       pt2.x = rng.uniform( x_1, x_2 );
       pt2.y = rng.uniform( y_1, y_2 );

       rectangle( image, pt1, pt2, [self randomColor], MAX( thickness, -1 ), lineType );

     }
}

-(void)Drawing_Random_Ellipses:(Mat)image{
    int lineType = 8;
    for ( int i = 0; i < NUMBER; i++ )
    {
        cv::Point center;
      center.x = rng.uniform(x_1, x_2);
      center.y = rng.uniform(y_1, y_2);

        cv::Size axes;
      axes.width = rng.uniform(0, 200);
      axes.height = rng.uniform(0, 200);

      double angle = rng.uniform(0, 180);

      ellipse( image, center, axes, angle, angle - 100, angle + 200,
               [self randomColor], rng.uniform(-1,9), lineType );

    }

}

-(void)Drawing_Random_Polylines:(Mat)image{
    int lineType = 8;

     for( int i = 0; i< NUMBER; i++ )
     {
         cv::Point pt[2][3];
       pt[0][0].x = rng.uniform(x_1, x_2);
       pt[0][0].y = rng.uniform(y_1, y_2);
       pt[0][1].x = rng.uniform(x_1, x_2);
       pt[0][1].y = rng.uniform(y_1, y_2);
       pt[0][2].x = rng.uniform(x_1, x_2);
       pt[0][2].y = rng.uniform(y_1, y_2);
       pt[1][0].x = rng.uniform(x_1, x_2);
       pt[1][0].y = rng.uniform(y_1, y_2);
       pt[1][1].x = rng.uniform(x_1, x_2);
       pt[1][1].y = rng.uniform(y_1, y_2);
       pt[1][2].x = rng.uniform(x_1, x_2);
       pt[1][2].y = rng.uniform(y_1, y_2);

         const  cv::Point* ppt[2] = {pt[0], pt[1]};
       int npt[] = {3, 3};

       polylines(image, ppt, npt, 2, true,  [self randomColor], rng.uniform(1,10), lineType);

     }
}

-(void)Drawing_Random_Filled_Polygons:(Mat)image{
    int lineType = 8;

     for ( int i = 0; i < NUMBER; i++ )
     {
         cv::Point pt[2][3];
       pt[0][0].x = rng.uniform(x_1, x_2);
       pt[0][0].y = rng.uniform(y_1, y_2);
       pt[0][1].x = rng.uniform(x_1, x_2);
       pt[0][1].y = rng.uniform(y_1, y_2);
       pt[0][2].x = rng.uniform(x_1, x_2);
       pt[0][2].y = rng.uniform(y_1, y_2);
       pt[1][0].x = rng.uniform(x_1, x_2);
       pt[1][0].y = rng.uniform(y_1, y_2);
       pt[1][1].x = rng.uniform(x_1, x_2);
       pt[1][1].y = rng.uniform(y_1, y_2);
       pt[1][2].x = rng.uniform(x_1, x_2);
       pt[1][2].y = rng.uniform(y_1, y_2);

         const cv::Point* ppt[2] = {pt[0], pt[1]};
       int npt[] = {3, 3};
       fillPoly( image, ppt, npt, 2,[self randomColor], lineType );
     }
}

-(void)Drawing_Random_Circles:(Mat)image{
    int lineType = 8;

     for (int i = 0; i < NUMBER; I++)
     {
         cv::Point center;
       center.x = rng.uniform(x_1, x_2);
       center.y = rng.uniform(y_1, y_2);

       circle( image, center, rng.uniform(0, 300), [self randomColor],
               rng.uniform(-1, 9), lineType );
     }
}

-(void)Displaying_Random_Text:(Mat)image{
    int lineType = 8;

    for ( int i = 1; i < NUMBER; i++ )
    {
        cv::Point org;
      org.x = rng.uniform(x_1, x_2);
      org.y = rng.uniform(y_1, y_2);

      putText( image, "Testing text rendering", org, rng.uniform(0,8),
               rng.uniform(0,100)*0.05+0.1,[self randomColor], rng.uniform(1, 10), lineType);
    }

}

-(void)Displaying_Big_End:(Mat)image{
    cv::Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);
    cv::Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2);
     int lineType = 8;

     Mat image2;
  UIImageView * imageView;
     for( int i = 0; i < 255; i += 2 )
     {
       image2 = image - Scalar::all(i);
       putText( image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,
                Scalar(i, i, 255), 5, lineType );
        imageView = [self createImageViewInRect:self.view.bounds];
              [self.view addSubview:imageView];
              imageView.image  = [self UIImageFromCVMat:image2];

     }
  
  
}



-(Scalar)randomColor{
    int icolor = (unsigned) rng;
    return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
}


#pragma mark  - private
-(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat
{
    //    mat 是brg 而 rgb
    Mat src;
    NSData *data=nil;
    CGBitmapInfo info =kCGImageAlphaNone|kCGBitmapByteOrderDefault;
    CGColorSpaceRef colorSpace;
    if (cvMat.elemSize() == 1) {
        colorSpace = CGColorSpaceCreateDeviceGray();
        data= [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];
    } else if(cvMat.elemSize() == 3){
        cvtColor(cvMat, src, COLOR_BGR2RGB);
        data= [NSData dataWithBytes:src.data length:src.elemSize()*src.total()];
        colorSpace = CGColorSpaceCreateDeviceRGB();
    }else{
        colorSpace = CGColorSpaceCreateDeviceRGB();
        cvtColor(cvMat, src, COLOR_BGRA2RGBA);
        data= [NSData dataWithBytes:src.data length:src.elemSize()*src.total()];
        info =kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault;
    }
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
    // Creating CGImage from cv::Mat
    CGImageRef imageRef = CGImageCreate(cvMat.cols,                                 //width
                                        cvMat.rows,                                 //height
                                        8,                                          //bits per component
                                        8 * cvMat.elemSize(),                       //bits per pixel
                                        cvMat.step[0],                            //bytesPerRow
                                        colorSpace,                                 //colorspace
                                        kCGImageAlphaNone|kCGBitmapByteOrderDefault,// bitmap info
                                        provider,                                   //CGDataProviderRef
                                        NULL,                                       //decode
                                        false,                                      //should interpolate
                                        kCGRenderingIntentAbsoluteColorimetric                   //intent
                                        );
    // Getting UIImage from CGImage
    UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);
    return finalImage;
}


/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

3.说明

  • 1.让我们检视 main 函数。我们发现第一步是实例化一个 Random Number Generator(随机数发生器对象) (RNG):
RNG rng( 0xFFFFFFFF );

RNG的实现了一个随机数发生器。 在上面的例子中, rng 是用数值 0xFFFFFFFF 来实例化的一个RNG对象。

  • 2.然后我们初始化一个 0 矩阵(代表一个全黑的图像), 并且指定它的宽度,高度,和像素格式:
Mat image = Mat::zeros( window_height, window_width, CV_8UC3 );

  • 3.然后我们开始疯狂的绘制。看过代码时候你会发现它主要分八个部分,正如函数定义的一样:
    [self Drawing_Random_Lines:image];
    [self Drawing_Random_Rectangles:image];
    [self Drawing_Random_Ellipses:image];
    [self Drawing_Random_Polylines:image];
    [self Drawing_Random_Filled_Polygons:image];
    [self Drawing_Random_Circles:image];
    [self Displaying_Random_Text:image];
    [self Displaying_Big_End:image];

所有这些范数都遵循相同的模式,所以我们只分析其中的一组,因为这适用于所有。

    1. 查看函数 Drawing_Random_Lines:
-(void)Drawing_Random_Lines:(Mat)image{
    cv::Point pt1, pt2;

     for( int i = 0; i < NUMBER; i++ )
     {
       pt1.x = rng.uniform( x_1, x_2 );
       pt1.y = rng.uniform( y_1, y_2 );
       pt2.x = rng.uniform( x_1, x_2 );
       pt2.y = rng.uniform( y_1, y_2 );

       line(image, pt1, pt2, [self randomColor], rng.uniform(1, 10), 8 );
     }
}
  • for 循环将重复 NUMBER 次。 并且函数 line 在循环中, 这意味着要生成 NUMBER 条线段。
  • 线段的两个端点分别是 pt1 和 pt2. 对于 pt1 我们看到:

我们知道 rng 是一个 随机数生成器 对象。在上面的代码中我们调用了 rng.uniform(a,b) 。这指定了一个在 a 和 b 之间的均匀分布(包含 a, 但不含 b)。
由上面的说明,我们可以推断出 pt1 和 pt2 将会是随机的数值,因此产生的线段是变幻不定的,这会产生一个很好的视觉效果(从下面绘制的图片可以看出)。
我们还可以发现, 在 line 的参数设置中,对于 color 的设置我们用了:

-(Scalar)randomColor{
   int icolor = (unsigned) rng;
   return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
}

正如我们看到的,函数的返回值是一个用三个随机数初始化的 Scalar 对象,这三个随机数代表了颜色的 R, G, B 分量。所以,线段的颜色也是随机的!

  • 5上面的解释同样适用于其它的几何图形,比如说参数 center(圆心) 和 vertices(顶点) 也是随机的。
    1. 在结束之前,我们还应该看看函数 Display_Random_Text 和 Displaying_Big_End, 因为它们有一些有趣的特征:
  • 7.Display_Random_Text:
-(void)Displaying_Random_Text:(Mat)image{
    int lineType = 8;

    for ( int i = 1; i < NUMBER; i++ )
    {
        cv::Point org;
      org.x = rng.uniform(x_1, x_2);
      org.y = rng.uniform(y_1, y_2);

      putText( image, "Testing text rendering", org, rng.uniform(0,8),
               rng.uniform(0,100)*0.05+0.1,[self randomColor], rng.uniform(1, 10), lineType);
    }

}

函数 putText 都做了些什么?在我们的例子中:

  • image 上绘制文字 “Testing text rendering”
  • 文字的左下角将用点 org 指定。
  • 字体参数是用一个在[0,8)之间的整数来定义。
  • 字体的缩放比例是用表达式 rng.uniform(0, 100)x0.05 + 0.1 指定(表示它的范围是 [0.1,5.1)
  • 字体的颜色是随机的 (记为 [self randomColor])。
  • 字体的粗细范围是从 1 到 10, 表示为 rng.uniform(1,10)
    因此, 我们将绘制 (与其余函数类似) NUMBER 个文字到我们的图片上,以位置随机的方式。
  • 8 Displaying_Big_End
-(void)Displaying_Big_End:(Mat)image{
    cv::Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);
    cv::Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2);
     int lineType = 8;

     Mat image2;

     for( int i = 0; i < 255; i += 2 )
     {
       image2 = image - Scalar::all(i);
       putText( image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,
                Scalar(i, i, 255), 5, lineType );

     }
}

除了 getTextSize (用于获取文字的大小参数), 我们可以发现在 for 循环里的新操作:

  image2 = image - Scalar::all(i)

**image2** 是 **image** 和 **Scalar::all(i)** 的差。事实上,**image2** 的每个像素都是 **image** 的每个像素减去 **i** (对于每个像素,都是由R,G,B三个分量组成,每个分量都会独立做差)的差。

我们还要知道,减法操作 总是 保证是 合理 的操作, 这表明结果总是在合理的范围内 (这个例子里结果不会为负数,并且保证在 0~255的合理范围内)。

5结果

截取一部分结果展示





github 地址
摘录博客
源码地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容