转:ios通过摄像头获取特定数据(http://www.2cto.com/kf/201404/290777.html)

凝视: 因为近期项目需求,须要一个可以实现对摄像头图片获取当中部分内容的功能,类似于二维码扫描。

可是仅仅须要获取特定位置的像素块进行简单计算就可以,所以听上去还是非常easy的。可是经过实践,发现,现实似乎与想象中不一样,因为摄像头拍到的数据,採用的是QZ(也就是CG框架)进行绘制。所以涉及到坐标系与frame的坐标系不一致的问题。

1:尝试直接拿到摄像头数据,先输出看下。 code: 代码略。 

总结: 直接使用摄像头数据再用imageView的方式显示出来的时刻。我们发现,数据是正确的==。所见即所得的方式。 须要注意的是: 当图片是横向拍摄的时刻。我们能够看到。相机会自己主动将图片进行90度旋转,也就是说。系统在你横向拍摄的时刻。会自己主动将图片旋转90度。满足你正常情况下的观看。

所以: 我们使用imageView对拿到的数据进行展示的时刻,数据并没有颠倒的现象。

为了防止出现这个现象的原因是出于imageView的内部实现,我们使用CgimageRef的方式。再次验证 从摄像头拿到的数据真的和我们所示一样吗? 

code:

CGImageRef oldImageRef=image.CGImage;

UIImage* newImage=[UIImage imageWithCGImage:oldImageRef];

凝视: 

在这里,我们仅仅是对拿到的Image对象,先转换成了CGimage。再使用UIImage的方法得到新的Image对象。 

结果:我们发现,得到的图像果然就是旋转90度的图片。而不再是原图了。

UIImage* newImage=[UIImage imageWithCGImage:oldImageRef scale:.1 orientation:UIImageOrientationRight];

使用上面的语句,能够将图像旋转90度变成我们须要的样子。

思考: 

这么简单的变化中,图片会不会丢失数据? ---------

NSData* data=UIImageJPEGRepresentation(image, 0);

NSLog(@"%lu",(unsigned long)data.length);



还好,数据没有丢失。既然数据没有丢失,那么我们应该能够获取到当中特定的一块数据得出。再显示出来才对。 

问题来了: 我们要获取某一块数据的内容,我们应该怎么传递rect呢?由于我们默认的rect与CG的坐标系并不同。是否须要转换呢? 







1:我们先试一下,先把数据转过来。再从里面拿一部分. code:

CGImageRef imageRef=image.CGImage;

CGImageRef newimage=CGImageCreateWithImageInRect(imageRef, rect);

结果发现: 拿到的数据还是倾斜了90度。也就是说,我们上面对数据这种转换事实上根本没有起到作用,数据在底层存储的方式就是使用CG的坐标系存储的。 

经过试验发现,[UIImage imageWithCGImage:oldImageRef scale:.1 orientation:UIImageOrientationRight]中,对orientation的改变。不会对我们的实验结果产生不论什么影响。 也就是说,这种方法,事实上并没有对底层的数据进行操作,而仅仅只是是在初始化新的UIImage的时刻,对底层像素的读取,orientation不同。方向也不同而已。 

思考: 

由于,我们使用上面的方法,并没有操作究竟层的像素矩阵。也就是我。我们假设想要解决问题,有两种方式, 1:将底层数据矩阵转换成我们须要的相应坐标系的内容。

这也就是CTM转换。 将Image对象内部数据进行转换。

code:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
-
(UIImage *)image:(UIImage *)image rotation:(UIImageOrientation)orientation
{
    longdoublerotate
=
0.0;
    CGRect
rect;
    floattranslateX
=
0;
    floattranslateY
=
0;
    floatscaleX
=
1.0;
    floatscaleY
=
1.0;
     
    switch(orientation)
{
        caseUIImageOrientationLeft:
            rotate
= M_PI_2;
            rect
= CGRectMake(
0,0,
image.size.height, image.size.width);
            translateX
=
0;
            translateY
= -rect.size.width;
            scaleY
= rect.size.width/rect.size.height;
            scaleX
= rect.size.height/rect.size.width;
            break;
        caseUIImageOrientationRight:
            rotate
=
3*
M_PI_2;
            rect
= CGRectMake(
0,0,
image.size.height, image.size.width);
            translateX
= -rect.size.height;
            translateY
=
0;
            scaleY
= rect.size.width/rect.size.height;
            scaleX
= rect.size.height/rect.size.width;
            break;
        caseUIImageOrientationDown:
            rotate
= M_PI;
            rect
= CGRectMake(
0,0,
image.size.width, image.size.height);
            translateX
= -rect.size.width;
            translateY
= -rect.size.height;
            break;
        default:
            rotate
=
0.0;
            rect
= CGRectMake(
0,0,
image.size.width, image.size.height);
            translateX
=
0;
            translateY
=
0;
            break;
    }
     
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef
context = UIGraphicsGetCurrentContext();
    //做CTM变换
    CGContextTranslateCTM(context,0.0,
rect.size.height);
    CGContextScaleCTM(context,1.0,
-
1.0);
    CGContextRotateCTM(context,
rotate);
    CGContextTranslateCTM(context,
translateX, translateY);
     
    CGContextScaleCTM(context,
scaleX, scaleY);
    //绘制图片
    CGContextDrawImage(context,
CGRectMake(
0,0,
rect.size.width, rect.size.height), image.CGImage);
     
    UIImage
*newPic = UIGraphicsGetImageFromCurrentImageContext();
     
    returnnewPic;
}

结论:

这里的解决方式。就是对底层像素矩阵进行装换之后,在对里面数据截取一部分。

能够解决截取部分内容的问题。

-------------------

2:解决方式二:就是对rect进行装换。依据数据底层,进行rect的转换。

直接获取摄像头传回的图像数据(人脸、微笑、眨眼: 识别-->第一步):图像识别第一步的更多相关文章

  1. OpenCV 学习笔记 05 人脸检测和识别

    本节将介绍 Haar 级联分类器,通过对比分析相邻图像区域来判断给定图像或子图像与已知对象是否匹配. 本章将考虑如何将多个  Haar 级联分类器构成一个层次结构,即一个分类器能识别整体区域(如人脸) ...

  2. MATLAB获取“非免驱的相机或者摄像头”的图像数据

    Image Acquisition Toolbox™ Adaptor Kit 图像採集工具箱 当要使用MATLAB获取"非免驱的相机或者摄像头"的图像数据时,须要开发一个插件,MA ...

  3. vc/mfc获取rgb图像数据后动态显示及保存图片的方法

    vc/mfc获取rgb图像数据后动态显示及保存图片的方法 该情况可用于视频通信中获取的位图数据回放显示或显示摄像头捕获的本地图像 第一种方法 #include<vfw.h> 加载 vfw3 ...

  4. Opencv+MFC获取摄像头数据,显示在Picture控件

    分为两步:OpenCV获取摄像头数据+图像在Picture上显示 第一步:OpenCV获取摄像头数据 参考:http://www.cnblogs.com/epirus/archive/2012/06/ ...

  5. Hi3516开发笔记(十):Qt从VPSS中获取通道图像数据存储为jpg文件

    前言   上一篇已经将himpp套入qt的基础上进行开发.那么qt中拿到frame则是很关键的交互,这是qt与海思可能编解码交叉开发的关键步骤.   受限制   因为直接配置sample的vi比较麻烦 ...

  6. C++ DirectShow读取摄像头后然后保存图像数据

    #include <stdio.h> #include "camerads.h" #include <highgui.h> const char *g_sz ...

  7. 使用OpenCV通过摄像头捕获实时视频并探测人脸

    在Opencv初接触,图片的基本操作这篇手记中,我介绍了一些图片的基本操作,视频可以看作是一帧一帧的图片,因此图片操作其实是视频操作的基础,这篇手记就来讲讲OpenCV中的视频操作,并实现一个用笔记本 ...

  8. 人脸检测及识别python实现系列(3)——为模型训练准备人脸数据

    人脸检测及识别python实现系列(3)——为模型训练准备人脸数据 机器学习最本质的地方就是基于海量数据统计的学习,说白了,机器学习其实就是在模拟人类儿童的学习行为.举一个简单的例子,成年人并没有主动 ...

  9. 人脸检测及识别python实现系列(1)——配置、获取实时视频流

    人脸检测及识别python实现系列(1)——配置.获取实时视频流 1. 前言 今天用多半天的时间把QQ空间里的几篇年前的旧文搬到了这里,算是完成了博客搬家.QQ空间里还剩下一些记录自己数学学习路线的学 ...

随机推荐

  1. Hibernate学习笔记三:常用数据库操作语句

    转载请注明原文地址: 一:HQL 1:HQL语句格式:select from POJO类名 where 条件表达式 group by 属性 having 聚集函数 order by 属性 [其中,fr ...

  2. JSP九大内置对象辨析

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6043096.html JSP中一共预先定义了9个这样的对象,分别为:request.response.sess ...

  3. Linux内核中的软中断、tasklet和工作队列具体解释

    [TOC] 本文基于Linux2.6.32内核版本号. 引言 软中断.tasklet和工作队列并非Linux内核中一直存在的机制,而是由更早版本号的内核中的"下半部"(bottom ...

  4. java HMAC_SHA1加密算法

      java HMAC_SHA1加密算法 CreationTime--2018年7月14日16点46分 Author:Marydon 1.准备工作 import javax.crypto.Mac; i ...

  5. ROS中利用V-rep进行地图构建仿真

    V-rep中显示激光扫描点  在VREP自带的场景中找到practicalPathPlanningDemo.ttt文件,删除场景中多余的物体只保留静态的地图.然后在Model browser→comp ...

  6. 【转】UIAutomator源码分析之启动和运行

    我们可以看到UiAutomator其实就是使用了UiAutomation这个新框架,通过调用AccessibilitService APIs来获取窗口界面控件信息已经注入用户行为事件,那么今天开始我们 ...

  7. Qt5中创建临时的后台线程。

    有个需求就是,GUI图形界面在上传文件到服务器的时候,需要用zip命令行打包,因为文件很多的时候,zip命令打包需要计算很长时间,所以把这样计算量大的任务分离到后台线程比较合适,然后任务完成,以信号槽 ...

  8. c++ 多个线程读一个线程写同步

    这种情况一般多个线程读是不需要加锁的.就在写的时候需要加锁. 那么要做的就是让不写的时候,读不受同步限制.让多线程自由的读. 这个时候就要用读写锁 boost已经有读写锁,而c++ 14才有读写锁. ...

  9. 命令行参数解析函数getopt和getopt_long函数【转】

    原文地址:http://blog.csdn.net/cashey1991/article/details/7942809 getopt和getopt_long函数   平时在写程序时常常需要对命令行参 ...

  10. Webdriver设置Firefox自动下载

    看到很多人在firefox上操作下载窗口用autoit,太麻烦了,提供一种用profile来解决的办法: FirefoxProfile profile = new FirefoxProfile(); ...