<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>webcam &#8211; 编码无悔 /  Intent &amp; Focused</title>
	<atom:link href="https://www.codelast.com/tag/webcam/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.codelast.com</link>
	<description>最优化之路</description>
	<lastBuildDate>Sun, 03 May 2020 12:29:29 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>[原创]基于微信和Raspberry Pi的远程监控系统 / A Remote Monitoring System Based on WeChat &#038; Raspberry Pi</title>
		<link>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9f%ba%e4%ba%8e%e5%be%ae%e4%bf%a1%e5%92%8craspberry-pi%e7%9a%84%e8%bf%9c%e7%a8%8b%e7%9b%91%e6%8e%a7%e7%b3%bb%e7%bb%9f-a-remote-monitoring-system-based-on-wechat-raspberry-pi/</link>
					<comments>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9f%ba%e4%ba%8e%e5%be%ae%e4%bf%a1%e5%92%8craspberry-pi%e7%9a%84%e8%bf%9c%e7%a8%8b%e7%9b%91%e6%8e%a7%e7%b3%bb%e7%bb%9f-a-remote-monitoring-system-based-on-wechat-raspberry-pi/#comments</comments>
		
		<dc:creator><![CDATA[learnhard]]></dc:creator>
		<pubDate>Sun, 16 Mar 2014 14:47:19 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[remote monitoring system]]></category>
		<category><![CDATA[webcam]]></category>
		<category><![CDATA[wechat]]></category>
		<category><![CDATA[微信]]></category>
		<category><![CDATA[树莓派]]></category>
		<category><![CDATA[远程监控系统]]></category>
		<guid isPermaLink="false">http://www.codelast.com/?p=5374</guid>

					<description><![CDATA[<p>
<a href="http://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a>是什么？<br />
引用维基百科的一句话：</p>
<blockquote>
<p>
		The Raspberry Pi is a credit card sized single-board computer developed in the UK by the Raspberry Pi Foundation with the intention of stimulating the teaching of basic computer science in schools.</p>
</blockquote>
<p>简单地说，它就是一个基于ARM CPU的、信用卡那么大的迷你计算机。<br />
<span style="color: rgb(0, 0, 255); ">In short, Pi is an ARM-based mini computer which has a credit card size.</span>&#8230; <a href="https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9f%ba%e4%ba%8e%e5%be%ae%e4%bf%a1%e5%92%8craspberry-pi%e7%9a%84%e8%bf%9c%e7%a8%8b%e7%9b%91%e6%8e%a7%e7%b3%bb%e7%bb%9f-a-remote-monitoring-system-based-on-wechat-raspberry-pi/" class="read-more">Read More </a></p>]]></description>
										<content:encoded><![CDATA[<p>
<a href="http://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a>是什么？<br />
引用维基百科的一句话：</p>
<blockquote>
<p>
		The Raspberry Pi is a credit card sized single-board computer developed in the UK by the Raspberry Pi Foundation with the intention of stimulating the teaching of basic computer science in schools.</p>
</blockquote>
<p>简单地说，它就是一个基于ARM CPU的、信用卡那么大的迷你计算机。<br />
<span style="color: rgb(0, 0, 255); ">In short, Pi is an ARM-based mini computer which has a credit card size.</span></p>
<p>前段时间公司举行hackathon比赛，我做了一套如题所示的系统，整个过程太累了，连续30个小时没睡，简直要了我半条命，现在我打算把它的主要实现记下来。<br />
<span id="more-5374"></span><br />
在阅读本文之前，请确保你已经阅读过我的另外几篇<a href="http://www.codelast.com/?p=5013" target="_blank" rel="noopener noreferrer"><span style="background-color: rgb(255, 160, 122); ">关于Pi的文章</span></a>，因为本文与它们有或多或少的关系。<br />
<span style="color: rgb(0, 0, 255); ">Before reading this article, please make sure that you&#39;ve read&nbsp;<a href="http://www.codelast.com/?p=5013" target="_blank" rel="noopener noreferrer"><span style="background-color: rgb(255, 160, 122); ">some other articles</span></a>&nbsp;of mine on Pi</span><span style="color: rgb(0, 0, 255); ">, because this article is more or less based on them.</span></p>
<p><span style="background-color: rgb(0, 255, 0); ">【1】</span>本文主要内容 <span style="color:#ff0000;">/</span> <span style="color:#0000ff;">Main content of this article</span><br />
构建一个具有旋转自由度的远程监控系统，使用微信（WeChat）向树莓派发送指令，再由树莓派直接控制步进电机带动摄像头旋转、拍照，并将照片回传到微信上。<br />
将这样一套设备放在某个地方，就可以通过微信监控其周围的情况了。<br />
先看演示效果（收到了从微信发送的指令之后，摄像头就转动了）：<br />
<embed align="middle" allowfullscreen="true" allowscriptaccess="always" height="400" quality="high" src="http://player.youku.com/player.php/sid/XNjg1NzQ5NzM2/v.swf" type="application/x-shockwave-flash" width="480"></embed><br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color: rgb(0, 255, 0); ">【2】</span>实现方案 <span style="color:#ff0000;">/</span> <span style="color:#0000ff;">The implementation</span><br />
用下图表示：</p>
<div style="text-align: center;">
	<img decoding="async" alt="" src="https://www.codelast.com/wp-content/uploads/ckfinder/images/wechat_pi_monitoring_system_1_1.png" style="width: 400px; height: 323px;" /></div>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
最上方是用户，你就是你所处的位置。通过微信，用户添加了一个公众账号之后，可以向其发送消息。微信Server（腾讯的服务器）收到消息之后，会根据你在微信公众账号后台的设置，决定是直接回复这条消息（以固定内容），还是将其转发到另一台你自己指定的服务器上。显然，由于有树莓派的存在，我们必须要有另一台服务器（图中的&ldquo;Web Server&rdquo;）的存在，因为我们不可能将树莓派挂在微信Server上。</p>
<p>有了那台&ldquo;Web Server&rdquo;，Pi就可以与之通信，间接地收到来自微信Server（其实也就是用户）的指令了。收到指令后，Pi会执行它，要么拍照，要么控制步进电机带动摄像头转动。<br />
有人会说，为什么我们不能让微信Server直接与Pi交互？例如，我在Pi上架设一个Web Server，微信Server就可以直接和它通信了啊！<br />
没错，但是这样的条件要求太高了。这是因为：<br />
1）微信Server不接受任何服务器主动向它发送请求，只能是微信Server向其他服务器发送请求，其他服务器再回复；<br />
2）在中国的网络环境下，一个家庭宽带里接入的设备，通常都是没有公网IP的。如果你非要通过配置端口映射等方法来让外面的服务器可以直接访问到家里的服务器的话，配置太麻烦。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">【3】</span>中转服务器的角色<br />
中转服务器即图中的&ldquo;Web Server&rdquo;，它负责与微信Server交互、与Pi交互，将来自微信的指令转达到Pi那里，接收来自Pi的数据，等等。<br />
之所以叫它&ldquo;Web Server&rdquo;，是因为运行在其上的，是一个web应用程序。<br />
有人说，我自己从来都没有一台具有公网IP的服务器，怎么搭建这样一个web应用？不用急，有大量免费的互联网资源可以用！例如<a href="https://developers.google.com/appengine/" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">Google App Engine</span></a>（GAE），<a href="http://sae.sina.com.cn/" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">Sina App Engine</span></a>（SAE），<a href="http://developer.baidu.com/service" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">Baidu App Engine</span></a>（BAE），等等。<br />
这些*AE是什么东西？它们的学名可以统称为&ldquo;公有云计算平台&rdquo;，用人话说就是&ldquo;为你提供一台虚拟服务器，可以在上面搭建web应用程序&rdquo;。<br />
GAE在国内被墙了，SAE和BAE是仿GAE搞起来的，SAE比BAE先出世，于是我选了SAE。<br />
SAE支持在上面用Python、PHP、Java来开发web应用，像我开发的这个应用，SAE的免费配额够用好久了。<br />
另外我要提的是，SAE只是在最近，才开放了一个实时服务&mdash;&mdash;Channel。这个东西是个什么概念？你在SAE上的程序是不支持bind()的，也就是你不能写一个程序监听某个特定端口，来实现一个服务，SAE出于安全性考虑才做了这种限制。为了弥补这种缺陷，SAE推出了一种名为Channel的服务：</p>
<blockquote>
<p>
		&ldquo;Channel是SAE提供的实时消息推送服务。通过在浏览器和SAE服务端之间建立长连接，使得应用可以方便的向Javascript客户端实时的推送消息。开发者可以利用Channel服务开发自己的实时性要求比较高的应用，如游戏、在线聊天室、在线直播等。&rdquo;</p>
</blockquote>
<p>但是如果我没记错的话，它的文档中写过，最好不要通过Channel服务传送超过4K的数据&mdash;&mdash;这就有点弱了，要知道，摄像头拍摄的一张照片几乎是必须要超过4K的，所以，按我的理解，想通过SAE Channel服务来实时化中转服务器和Pi之间的交互，还是不现实的。<br />
因此，我干脆就把中转服务器弄得简单一点，不去想完全实时化的情景，而是在收到微信Server发来的指令后，存储在MySQL中，由Pi周期性轮循中转服务器来获取指令。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">【4】</span>微信Server是怎么将用户指令发到中转服务器上的<br />
首先你要创建一个微信公众账号，并申请成为一名微信开发者。然后，你在微信中查找并添加这个公众账号，就可以向它发送文本消息（即本文所说的指令）了。这个消息其实是发送到了微信Server上，至于微信Server是将该消息转发出去，还是直接以固定内容回复，这是由你在微信公众平台的后台设置的。在我的这个项目中，当然是让微信Server发送到我的中转服务器去处理，按微信Server的要求，必须要在5秒内给它回复（否则就无效了）。<br />
我个人觉得，微信的开发文档写得不好，有些至关重要的东西说得不明不白，很多人在微信开发者论坛中发帖问，才找到了答案。例如，一个&ldquo;订阅号&rdquo;是没有权限将图片之类的素材上传到微信Server上的，只有&ldquo;服务号才行，但是对我这样的个人来说，申请到&ldquo;服务号&rdquo;是完全不可能的事情，这就决定了我的技术方案要适应它&mdash;&mdash;我不能把Pi拍摄的照片发送到微信Server上，而只能放在中转服务器（SAE）上，只回传图片的public URL给微信。这也就导致了本系统的安全性得不到保证&mdash;&mdash;一个用户控制自己的Pi拍摄的照片，不应该可以在公网上被检索到。虽然SAE可以限制指定域名才能访问其Storage中的文件，但是我觉得这样安全性仍然不够。<br />
无论如何，在Hackathon比赛时间有限，我无法完善这个系统，能让它按设想的&ldquo;动起来&rdquo;，我就心满意足了。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">【5】</span>Pi控制步进电机以及摄像头拍照<br />
Pi控制摄像头拍照最终使用了V4L2来实现（具体可以看<a href="http://www.codelast.com/?p=7873" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">这里</span></a>），在Hackathon的过程中，我为了拍照程序不稳定的头疼问题折腾了一个多小时，最终达到了一个&ldquo;可接受&rdquo;的结果。<br />
至于Pi如何控制步进电机，这里也不详述了。</p>
<p><span style="background-color:#00ff00;">【6】</span>系统物理结构搭建<br />
这里说的物理结构搭建，是指我怎样把上面林林总总的各种东西用一个外壳包装起来？<br />
先看成品的实拍图：</p>
<div style="text-align: center;">
	<img decoding="async" alt="" src="https://www.codelast.com/wp-content/uploads/ckfinder/images/wechat_pi_monitoring_system_4.jpg" style="width: 450px; height: 431px;" /></div>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
近距离，仔细看摄像头和步进电机的连接方式：</p>
<div style="text-align: center;">
	<img decoding="async" alt="" src="https://www.codelast.com/wp-content/uploads/ckfinder/images/wechat_pi_monitoring_system_7.jpg" style="width: 486px; height: 309px;" /></div>
<p>俯视图：</p>
<div style="text-align: center;">
	<img decoding="async" alt="" src="https://www.codelast.com/wp-content/uploads/ckfinder/images/wechat_pi_monitoring_system_11.jpg" style="width: 470px; height: 610px;" /></div>
<p>你一下就明白了：这不是用乐高积木搭建起来的嘛！<br />
准确地说，是用山寨的乐高积木搭建起来的。淘宝上买的仿乐高货，积木个头很大一块，可以把树莓派、步进电机驱动板、步进电机很好地固定在中间，动弹不得，并且拆卸方便，对于一个实验性的系统来说，堪称完美包装器材。<br />
仔细看中间那张图，步进电机和摄像头是怎么连接在一起的？看起来简单，其实它是我花费了相当大的功夫，以损失了相当大的身体健康为代价才做出来的：<br />
首先，摄像头买来的时候有一个比较大的底座（市面上的非特殊定制的摄像头都差不多吧），由于两块&ldquo;乐高&rdquo;积木中间的空间容不下那么大的底座（并且底座也不是平的，会影响转动），所以必须要切割底座。切割是个痛苦的过程，电锯与塑料高速摩擦产生了很多有毒气体，味道很臭，我戴着PM 2.5的口罩仍然感觉无防护作用（真应该把3M的活性炭防毒面具带过去的）。<br />
但这只是第一步！<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
就算切割好了摄像头的底座，要把它粘贴到步进电机上那根细细的转轴上，也不是件容易的事情。为了让这个粘贴更牢靠，我的设计是：先切割一块圆的小亚克力板出来，中间钻个洞，刚好有电机轴那么大，然后先把这块小圆板固定、粘贴到电机转轴上，最后再把摄像头底座粘贴到这块亚克力板上。<br />
事实证明这样的设计粗陋却非常有效，最后摄像头被牢牢地固定在了步进电机上，并且不影响转动。</p>
<p><span style="background-color:#00ff00;">【7】</span>总结<br />
Hackathon是一种精神，或许我做的东西和牛人们的发明相比什么也不算，或许我做的东西和很多科技产品相比简陋无比，但是，它毕竟是我一点一滴做出来的，它的每根导线、每个流动的字节之间都流淌着我的血液，看到它出生的那一刻，那种激动的感觉无法形容！<br />
这也是我热爱技术的原因之一&mdash;&mdash;尽管我渺小，但是它却给了我想像发挥的空间，每个人都能在它里面找到自己的位置。</p>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a><br />
<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;版权声明&nbsp;<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;<br />
转载需注明出处：<u><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><em><span style="color: rgb(0, 0, 255);"><strong style="font-size: 16px;"><span style="font-family: arial, helvetica, sans-serif;">codelast.com</span></strong></span></em></a></u>&nbsp;<br />
感谢关注我的微信公众号（微信扫一扫）：</p>
<p style="border: 0px; font-size: 13px; margin: 0px 0px 9px; outline: 0px; padding: 0px; color: rgb(77, 77, 77);">
	<img decoding="async" alt="wechat qrcode of codelast" src="https://www.codelast.com/codelast_wechat_qr_code.jpg" style="width: 200px; height: 200px;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9f%ba%e4%ba%8e%e5%be%ae%e4%bf%a1%e5%92%8craspberry-pi%e7%9a%84%e8%bf%9c%e7%a8%8b%e7%9b%91%e6%8e%a7%e7%b3%bb%e7%bb%9f-a-remote-monitoring-system-based-on-wechat-raspberry-pi/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>[原创]在Raspberry Pi(树莓派)上调用V4L2来操纵摄像头拍照/Use V4L2 on Raspberry Pi to Controll a Webcam to Grab Images</title>
		<link>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9c%a8raspberry-pi%e6%a0%91%e8%8e%93%e6%b4%be%e4%b8%8a%e8%b0%83%e7%94%a8v4l2%e6%9d%a5%e6%93%8d%e7%ba%b5%e6%91%84%e5%83%8f%e5%a4%b4%e6%8b%8d%e7%85%a7use-v4l2-on-raspberry-pi-t/</link>
					<comments>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9c%a8raspberry-pi%e6%a0%91%e8%8e%93%e6%b4%be%e4%b8%8a%e8%b0%83%e7%94%a8v4l2%e6%9d%a5%e6%93%8d%e7%ba%b5%e6%91%84%e5%83%8f%e5%a4%b4%e6%8b%8d%e7%85%a7use-v4l2-on-raspberry-pi-t/#comments</comments>
		
		<dc:creator><![CDATA[learnhard]]></dc:creator>
		<pubDate>Fri, 14 Mar 2014 17:33:23 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry Pi/树莓派]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[grab image]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[take photo]]></category>
		<category><![CDATA[V4L2]]></category>
		<category><![CDATA[Video4Linux]]></category>
		<category><![CDATA[webcam]]></category>
		<category><![CDATA[树莓派]]></category>
		<guid isPermaLink="false">http://www.codelast.com/?p=7873</guid>

					<description><![CDATA[<p>
<a href="http://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a>是什么？<br />
引用维基百科的一句话：</p>
<blockquote>
<p>
		The Raspberry Pi is a credit card sized single-board computer developed in the UK by the Raspberry Pi Foundation with the intention of stimulating the teaching of basic computer science in schools.</p>
</blockquote>
<p>简单地说，它就是一个基于ARM CPU的、信用卡那么大的迷你计算机。</p>
<p>我曾经写过<a href="http://www.codelast.com/?p=5014" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">一篇教程</span></a>，展示了如何调用OpenCV，来控制摄像头拍照。在那篇文章的末尾，我提到了一个遗留问题，即把抓取图像的尺寸设置得稍高一点的时候，那个程序就很容易崩溃；在图像尺寸设置得很低的时候，有时候也会崩溃，我一直没弄明白为什么。<br />
但是在前段时间，由于参赛原因，被迫在很短的时间内解决这个棘手的问题。真可谓是搜了无数网页，最后采取了一种折衷的方式&#8220;在很大程度上&#8221;解决了这个问题&#8212;&#8212;毕竟还不完美。<br />
<span id="more-7873"></span><br />
所以在这篇文章里，我打算介绍另一种方式来实现控制摄像头拍照，并且程序稳定得多（尽管程序还是会崩溃，但比OpenCV的版本少多了）。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a>&#8230; <a href="https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9c%a8raspberry-pi%e6%a0%91%e8%8e%93%e6%b4%be%e4%b8%8a%e8%b0%83%e7%94%a8v4l2%e6%9d%a5%e6%93%8d%e7%ba%b5%e6%91%84%e5%83%8f%e5%a4%b4%e6%8b%8d%e7%85%a7use-v4l2-on-raspberry-pi-t/" class="read-more">Read More </a></p>]]></description>
										<content:encoded><![CDATA[<p>
<a href="http://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a>是什么？<br />
引用维基百科的一句话：</p>
<blockquote>
<p>
		The Raspberry Pi is a credit card sized single-board computer developed in the UK by the Raspberry Pi Foundation with the intention of stimulating the teaching of basic computer science in schools.</p>
</blockquote>
<p>简单地说，它就是一个基于ARM CPU的、信用卡那么大的迷你计算机。</p>
<p>我曾经写过<a href="http://www.codelast.com/?p=5014" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">一篇教程</span></a>，展示了如何调用OpenCV，来控制摄像头拍照。在那篇文章的末尾，我提到了一个遗留问题，即把抓取图像的尺寸设置得稍高一点的时候，那个程序就很容易崩溃；在图像尺寸设置得很低的时候，有时候也会崩溃，我一直没弄明白为什么。<br />
但是在前段时间，由于参赛原因，被迫在很短的时间内解决这个棘手的问题。真可谓是搜了无数网页，最后采取了一种折衷的方式&ldquo;在很大程度上&rdquo;解决了这个问题&mdash;&mdash;毕竟还不完美。<br />
<span id="more-7873"></span><br />
所以在这篇文章里，我打算介绍另一种方式来实现控制摄像头拍照，并且程序稳定得多（尽管程序还是会崩溃，但比OpenCV的版本少多了）。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">『1』</span>把OpenCV换掉，选择知多少<br />
当时我第一个想法就是把OpenCV换掉，但是我还有什么选择呢？我先找到了<a href="https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/robot/image_processing/" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">这个网页</span></a>，它介绍了一种使用Python抓取摄像头图像的方法。但有个问题：如果你没有安装他们移植的系统（我应该没理解错吧...），那么就只能先按照要求安装他们提供的一些自定义library。很不巧，我使用的是Arch Linux ARM，所以当然要安装。不过，当我打开安装说明页之后，照做了几步之后，我就放弃了，因为太麻烦，路径都还要自己根据情况修改的，等我完全搞好之后，估计一个小时都过去了，而且还不一定能成。<br />
于是我又找到了若干篇用V4L来实现图像抓取的文章（<a href="http://linuxtv.org/downloads/v4l-dvb-apis/v4l2grab-example.html" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">链接1</span></a>，<a href="http://www.lavrsen.dk/svn/motion/tags/3.2.11/video2.c" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">链接2</span></a>），于是我抄来代码，在几乎看不懂的情况下，硬着头皮尝试去小修小改。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">『2』</span>V4L2是什么<br />
从前面提供的链接里，大家可以看到&ldquo;V4L2 video picture grabber&rdquo;的说明。V4L2是什么？从&nbsp;<a href="http://en.wikipedia.org/wiki/Video4Linux" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">这个Wiki页面</span></a>&nbsp;的部分内容：</p>
<blockquote>
<div>
		Video4Linux or V4L is a video capture[1] and output device API and driver framework for the Linux kernel, supporting many USB webcams, TV tuners, and other devices. Video4Linux is closely integrated with the Linux kernel.</div>
<div>
		V4L2 is the second version of V4L. Video4Linux2 fixed some design bugs and started appearing in the 2.5.X kernels.</div>
</blockquote>
<div>
	我们知道了V4L2是Linux内核的视频抓取和输出设备API和驱动框架，它支持非常多的USB摄像头等设备。所以，用它可以驱动摄像头抓取图像。<br />
	<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
	<span style="background-color:#00ff00;">『3』</span>输出什么格式的图片<br />
	显然，我们想要摄像头抓取并输出jpg，png之类的图片，但是，前面链接1里的代码输出的是PPM格式的图片。于是我看到了这行代码：</p>
<pre class="brush:cpp;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
</pre>
</div>
<p>这里显然是控制文件格式的。根据前面的链接2，我把它改成了jpg格式：</p>
<pre class="brush:cpp;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
// ...
if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) {
  printf(&quot;Libv4l didn&#39;t accept jpg format. Can&#39;t proceed.\n&quot;);
  exit(EXIT_FAILURE);
}
</pre>
<p>可惜的是编译运行之后发现这里过不去，也就是不支持jpg格式。于是只能输出PPM格式的图片。PPM是&ldquo;可移植像素图格式&rdquo;的简称，它是没有压缩的，文件体积较大（一个640＊480的PPM图片竟然有900多K），所以它既不利于存储也不利于网络传输。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">『4』</span>PPM图片转换为jpg格式<br />
前面我说过，最终得到摄像头抓取图片的方式是一种折衷的方式，这里就是一个体现：先拿到PPM，再转为jpg，实在是不得已而为之，因为通过调用V4L2抓取图像比较稳定，而我又无法让抓取图像的程序直接输出jpg格式的图片，因此就再转一下。<br />
找来找去发现了用<a href="http://www.imagemagick.org/" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">ImageMagick</span></a>转格式很容易。于是先安装：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
pacman -S imagemagick
</pre>
<p>安装好之后，它就带了一个名为&ldquo;convert&rdquo;的程序，转换命令不要太简单：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
convert 1.ppm 1.jpg
</pre>
<p>这样就把1.ppm转换成了1.jpg。对320＊240大小的图片，我感觉转换速度是非常快的。<br />
<span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">『5』</span>完整代码<br />
程序文件名为 <span style="color:#0000ff;">webcam-stable.c</span>&nbsp;：</p>
<pre class="brush:cpp;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;errno.h&gt;
#include &lt;sys/ioctl.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/time.h&gt;
#include &lt;sys/mman.h&gt;
#include &lt;linux/videodev2.h&gt;
#include &lt;libv4l2.h&gt;
#include &lt;libv4l1.h&gt;

/**
 * A program to capture image via the camera. 
 *
 * @author Darran Zhang @ codelast.com
 */

#define CLEAR(x) memset(&amp;(x), 0, sizeof(x))

struct buffer {
  void   *start;
  size_t length;
};

static void xioctl(int fh, int request, void *arg)
{
  int r;

  do {
    r = v4l2_ioctl(fh, request, arg);
  } while (r == -1 &amp;&amp; ((errno == EINTR) || (errno == EAGAIN)));

  if (r == -1) {
    fprintf(stderr, &quot;error %d, %s\n&quot;, errno, strerror(errno));
    exit(EXIT_FAILURE);
  }
}

int main(int argc, char **argv) {
  if (argc &lt; 4) {
    printf(&quot;Usage: ./webcam [outputImagePath] [outputImageWidth] [outputImageHeight]\nE.g. ./webcam webcam.jpg 320 240\n&quot;);
    return 1;
  }

  char* outputImagePath = argv[1];
  int imageWidth = atoi(argv[2]);
  int imageHeight = atoi(argv[3]);

  struct v4l2_format              fmt;
  struct v4l2_buffer              buf;
  struct v4l2_requestbuffers      req;
  enum v4l2_buf_type              type;
  fd_set                          fds;
  struct timeval                  tv;
  int                             r, fd = -1;
  unsigned int                    i, n_buffers;
  char                            *dev_name = &quot;/dev/video0&quot;;
  char                            out_name[256];
  FILE                            *fout;
  struct buffer                   *buffers;

  fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
  if (fd &lt; 0) {
    perror(&quot;Cannot open device&quot;);
    exit(EXIT_FAILURE);
  }

  CLEAR(fmt);
  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  fmt.fmt.pix.width       = imageWidth;
  fmt.fmt.pix.height      = imageHeight;
  fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
  //fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
  fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
  xioctl(fd, VIDIOC_S_FMT, &amp;fmt);
  if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
    printf(&quot;Libv4l didn&#39;t accept RGB24 format. Can&#39;t proceed.\n&quot;);
    exit(EXIT_FAILURE);
  }
  if ((fmt.fmt.pix.width != imageWidth) || (fmt.fmt.pix.height != imageHeight))
    printf(&quot;Warning: driver is sending image at %dx%d\n&quot;, fmt.fmt.pix.width, fmt.fmt.pix.height);

  CLEAR(req);
  req.count = 2;
  req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  req.memory = V4L2_MEMORY_MMAP;
  xioctl(fd, VIDIOC_REQBUFS, &amp;req);

  buffers = calloc(req.count, sizeof(*buffers));
  for (n_buffers = 0; n_buffers &lt; req.count; ++n_buffers) {
    CLEAR(buf);

    buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory      = V4L2_MEMORY_MMAP;
    buf.index       = n_buffers;

    xioctl(fd, VIDIOC_QUERYBUF, &amp;buf);

    buffers[n_buffers].length = buf.length;
    buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
      PROT_READ | PROT_WRITE, MAP_SHARED,
      fd, buf.m.offset);

    if (MAP_FAILED == buffers[n_buffers].start) {
      perror(&quot;mmap&quot;);
      exit(EXIT_FAILURE);
    }
  }

  for (i = 0; i &lt; n_buffers; ++i) {
    CLEAR(buf);
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;
    buf.index = i;
    xioctl(fd, VIDIOC_QBUF, &amp;buf);
  }
  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

  xioctl(fd, VIDIOC_STREAMON, &amp;type);

  do {
    FD_ZERO(&amp;fds);
    FD_SET(fd, &amp;fds);

    /* Timeout. */
    tv.tv_sec = 2;
    tv.tv_usec = 0;

    r = select(fd + 1, &amp;fds, NULL, NULL, &amp;tv);
  } while ((r == -1 &amp;&amp; (errno = EINTR)));
  if (r == -1) {
    perror(&quot;select&quot;);
    return errno;
  }

  CLEAR(buf);
  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buf.memory = V4L2_MEMORY_MMAP;
  xioctl(fd, VIDIOC_DQBUF, &amp;buf);

  fout = fopen(outputImagePath, &quot;w&quot;);
  if (!fout) {
    perror(&quot;Cannot open image&quot;);
    exit(EXIT_FAILURE);
  }
  fprintf(fout, &quot;P6\n%d %d 255\n&quot;,
    fmt.fmt.pix.width, fmt.fmt.pix.height);
  fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
  fclose(fout);

  xioctl(fd, VIDIOC_QBUF, &amp;buf);


  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  xioctl(fd, VIDIOC_STREAMOFF, &amp;type);
  for (i = 0; i &lt; n_buffers; ++i) {
    v4l2_munmap(buffers[i].start, buffers[i].length);
  }
  v4l2_close(fd);

  return 0;
}
</pre>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255);">http://www.codelast.com/</span></a><br />
编译：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
gcc webcam-stable.c -lv4l2 -o webcam-stable
</pre>
<p>程序运行时需要3个参数，分别是输出图片文件的路径、输出图片的宽度、输出图片的高度，例如：</p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
./webcam-stable /home/codelast/1.ppm 320 240
</pre>
<p>用一个脚本，在输出图片之后，再将其转为jpg格式，就完成了我们的任务。</p>
<p><span style="background-color:#00ff00;">『6』</span>总结<br />
<span style="background-color:#ee82ee;">[1]</span> 在解决上述问题的过程中，我遇到了无数的问题（例如编译时找不到某些库），因此为了解决那些问题，我安装了很多package，但我不确定它们是否全都需要，并且也没有来得及把它们全都记录下来，因此，我把记下来的写在这里，仅供参考：</p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
pacman -S xf86-video-v4l
</pre>
<p>
<span style="background-color:#ee82ee;">[2]</span> 这个程序比OpenCV版的程序要稳定得多，体现在抓取成功（程序不提示错误）的机会大得多，但我得承认，它还是有问题的，有时候会出错：</p>
<blockquote>
<p>
		error 12, Cannot allocate memory</p>
</blockquote>
<p>然后就没能抓下来图片。看这提示是内存不够（我是512MB的Pi）？但具体原因我还是不知道为什么，如果你知道怎么优化，请不吝赐教。</p>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a><br />
<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;版权声明&nbsp;<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;<br />
转载需注明出处：<u><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><em><span style="color: rgb(0, 0, 255);"><strong style="font-size: 16px;"><span style="font-family: arial, helvetica, sans-serif;">codelast.com</span></strong></span></em></a></u>&nbsp;<br />
感谢关注我的微信公众号（微信扫一扫）：</p>
<p style="border: 0px; font-size: 13px; margin: 0px 0px 9px; outline: 0px; padding: 0px; color: rgb(77, 77, 77);">
	<img decoding="async" alt="wechat qrcode of codelast" src="https://www.codelast.com/codelast_wechat_qr_code.jpg" style="width: 200px; height: 200px;" /></p>

			<!--[syntaxhighlighter]-->
			<!--代码高亮，请勿编辑-->
			<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shCore.js"></script><script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushCpp.js"></script>
<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushShell.js"></script>
<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushPlain.js"></script>

			<link type="text/css" rel="stylesheet" href="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/styles/shCoreCk.css" />
			<link type="text/css" rel="stylesheet" href="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/styles/shThemeCk.css" />
			<script type="text/javascript">
			SyntaxHighlighter.defaults['class-name']	= '';
			SyntaxHighlighter.defaults['smart-tabs']	= true;
			SyntaxHighlighter.defaults['tab-size']		= 2;
			SyntaxHighlighter.defaults['gutter']		= true;
			SyntaxHighlighter.defaults['quick-code']	= true;
			SyntaxHighlighter.defaults['collapse'] 		= false;
			SyntaxHighlighter.defaults['auto-links']	= true;
			SyntaxHighlighter.defaults['toolbar']		= true;
			SyntaxHighlighter.all();
			</script>
			<!--[/syntaxhighlighter]-->]]></content:encoded>
					
					<wfw:commentRss>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9c%a8raspberry-pi%e6%a0%91%e8%8e%93%e6%b4%be%e4%b8%8a%e8%b0%83%e7%94%a8v4l2%e6%9d%a5%e6%93%8d%e7%ba%b5%e6%91%84%e5%83%8f%e5%a4%b4%e6%8b%8d%e7%85%a7use-v4l2-on-raspberry-pi-t/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>[原创]在Raspberry Pi(树莓派)上用OpenCV来操纵摄像头拍照/Use OpenCV on Raspberry Pi to Controll a Webcam to Take Photos</title>
		<link>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9c%a8raspberry-pi%e4%b8%8a%e7%94%a8opencv%e6%9d%a5%e6%93%8d%e7%ba%b5%e6%91%84%e5%83%8f%e5%a4%b4%e6%8b%8d%e7%85%a7use-opencv-on-raspberry-pi-to-controll-a-webcam-to-take-photos/</link>
					<comments>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9c%a8raspberry-pi%e4%b8%8a%e7%94%a8opencv%e6%9d%a5%e6%93%8d%e7%ba%b5%e6%91%84%e5%83%8f%e5%a4%b4%e6%8b%8d%e7%85%a7use-opencv-on-raspberry-pi-to-controll-a-webcam-to-take-photos/#comments</comments>
		
		<dc:creator><![CDATA[learnhard]]></dc:creator>
		<pubDate>Thu, 18 Oct 2012 07:46:00 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Raspberry Pi/树莓派]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[Arch Linux ARM]]></category>
		<category><![CDATA[camera]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[webcam]]></category>
		<category><![CDATA[拍照]]></category>
		<category><![CDATA[摄像头]]></category>
		<category><![CDATA[教程]]></category>
		<guid isPermaLink="false">http://www.codelast.com/?p=5014</guid>

					<description><![CDATA[<p>
<span style="background-color:#00ff00;">For non-Chinese readers:</span><br />
<span style="color:#0000ff;">I&#39;m a software engineer in Shanghai, China. Since I bought a Raspberry Pi, I spent some spare time on it and I&#39;m glad to share something with Pi users all over the world, so this article has two languages: Chinese &#38; English, and I try to translate the Chinese to English as&#160;accurately as possible, but, there might be some translation mistakes, so if you don&#39;t know what I mean in the article, just leave a comment, and I&#39;ll reply when I get an answer.</span>&#8230; <a href="https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9c%a8raspberry-pi%e4%b8%8a%e7%94%a8opencv%e6%9d%a5%e6%93%8d%e7%ba%b5%e6%91%84%e5%83%8f%e5%a4%b4%e6%8b%8d%e7%85%a7use-opencv-on-raspberry-pi-to-controll-a-webcam-to-take-photos/" class="read-more">Read More </a></p>]]></description>
										<content:encoded><![CDATA[<p>
<span style="background-color:#00ff00;">For non-Chinese readers:</span><br />
<span style="color:#0000ff;">I&#39;m a software engineer in Shanghai, China. Since I bought a Raspberry Pi, I spent some spare time on it and I&#39;m glad to share something with Pi users all over the world, so this article has two languages: Chinese &amp; English, and I try to translate the Chinese to English as&nbsp;accurately as possible, but, there might be some translation mistakes, so if you don&#39;t know what I mean in the article, just leave a comment, and I&#39;ll reply when I get an answer. Also welcome to contact me via <a href="http://www.codelast.com/?page_id=2" target="_blank" rel="noopener noreferrer">Email</a>.</span></p>
<p><a href="http://www.raspberrypi.org/" target="_blank" rel="noopener noreferrer">Raspberry Pi</a>是什么？简单地说，它就是一个基于ARM CPU的、信用卡那么大的迷你计算机。<br />
<span style="color:#0000ff;">In short, Pi is an ARM-based mini computer which has a credit card size.</span></p>
<p>本文主要内容：<br />
在Raspberry Pi上，通过调用OpenCV库，自己写一个简单的C程序来控制摄像头拍照，并保存图片。<br />
在阅读本文之前，请确保你已经阅读过我的另一篇<a href="http://www.codelast.com/?p=4945" target="_blank" rel="noopener noreferrer">配置Pi的文章</a>，因为本文是在它的基础上进行的。<br />
<span style="color:#0000ff;">The main content of this article:<br />
Write a simple C program by invoking the OpenCV library on Raspberry Pi to control a webcam to take photos &amp; save them.<br />
Before reading this article, please make sure that you&#39;ve read my another article about <a href="http://www.codelast.com/?p=4945" target="_blank" rel="noopener noreferrer"><span style="background-color:#ffa07a;">Pi configuration</span></a>, because this article is based on that.</span><br />
<span id="more-5014"></span></p>
<div style="text-align: center; ">
	<span style="background-color: rgb(0, 255, 0); "><img decoding="async" alt="my running Raspberry Pi" src="https://www.codelast.com/wp-content/uploads/2012/10/my_running_raspberry_pi.jpg" style="width: 400px; height: 538px; " /></span></div>
<div style="text-align: center; ">
	<span style="color:#a52a2a;">图：我的Pi正在运行中 / my running Raspberry Pi</span></div>
<p>
<span style="background-color: rgb(0, 255, 0); ">【1】</span>安装OpenCV <span style="color:#ff0000;">/</span> <span style="color:#0000ff;">Install OpenCV</span><br />
命令：<br />
<span style="color:#0000ff;">Command:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
pacman -S opencv opencv-samples
</pre>
<p>上面的命令连OpenCV的sample一起装上了，这样我们在安装好之后就可以编译几个sample来测试。<br />
<span style="color:#0000ff;">This command will install the samples of OpenCV, too. So we can compile &amp; run several samples to have a test after the installation.</span></p>
<p><span style="background-color: rgb(0, 255, 0); ">【2】</span>带动摄像头 <span style="color:#ff0000;">/ </span><span style="color:#0000ff;">Drive the webcam</span><br />
在驱动已经可用的情况下，把一个USB摄像头接在USB口上也不一定能让它工作，因为Pi的USB口的电流供应可能不足。请看<a href="http://eduardofv.com/read_post/189-DIY-Powered-USB-Cable-for-Raspberry-Pi" target="_blank" rel="noopener noreferrer">这个链接</a>的玩家自制的一根增强供电的USB线，如果你想简单安全，那么你可以把摄像头接在一个有外部供电的USB HUB上，再把Pi的USB接到USB HUB上，这样摄像头的供电就充足了。<br />
<span style="color:#0000ff;">Plug the USB webcam into the USB interface of Pi might not able to make it work, even the driver has been available, because the current provided by Pi&#39;s USB interface may not be&nbsp;sufficient to drive a camera. You can learn to DIY a current-enhancement USB cable via </span><a href="http://eduardofv.com/read_post/189-DIY-Powered-USB-Cable-for-Raspberry-Pi" target="_blank" rel="noopener noreferrer"><span style="color:#0000ff;"><span style="background-color:#ffa07a;">this link</span></span></a><span style="color:#0000ff;">, but the easier way may be buying a powered USB HUB and use it to connect the webcam &amp; Pi.</span></p>
<p><span style="background-color: rgb(0, 255, 0); ">【3】</span>让opencv的sample跑起来 <span style="color:#ff0000;">/</span> <span style="color:#0000ff;">Run a sample of OpenCV</span><br />
为了验证在Pi上安装的OpenCV是可用的，所以至少要让一个sample可以跑起来。<br />
为了不把安装目录弄得一团乱，首先把安装好的OpenCV的sample目录拷贝到其他地方：<br />
<span style="color:#0000ff;">To make sure that the installed OpenCV related packages are &quot;correct&quot;, I decided to run at least one of the OpenCV samples.<br />
Copy the installed OpenCV sample directory to other place for the sake of not messing up the installation directory:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
mkdir /root/opencv
cp -r /usr/share/OpenCV/samples/ /root/opencv/
</pre>
<p>我们看到里面有&ldquo;c&rdquo;，&ldquo;cpp&rdquo;和&ldquo;gpu&rdquo;三种sample，选最简单的，我们进入&ldquo;c&rdquo;，先为所有文件加上写权限：<br />
<span style="color:#0000ff;">There are 3 kinds of samples in it, &quot;c&quot;, &quot;cpp&quot; &amp; &quot;gpu&quot;, so I choose the&nbsp;simplest - &quot;c&quot;, and enter the &quot;c&quot; directory, add write&nbsp;permission to all files:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
chmod +w *
</pre>
<p>然后我们看到&ldquo;c&rdquo;目录里有编译脚本&nbsp;<span style="color:#b22222;">build_all.sh</span>，执行它，看到出了一堆相似的错误，没有一个程序可以成功编译，例如以下错误：<br />
<span style="color:#0000ff;">Execute the </span><span style="color:#b22222;">build_all.sh</span><span style="color:#0000ff;"> script to compile an sample, then I got lots of similar errors, e.g. :</span></p>
<blockquote>
<div>
		[root@alarmpi c]# ./build_all.sh contours.c&nbsp;</div>
<div>
		&nbsp;compiling contours</div>
<div>
		&nbsp;/usr/bin/ld: /tmp/cch4zRSn.o: undefined reference to symbol &#39;lrint@@GLIBC_2.4&#39;</div>
<div>
		&nbsp;/usr/bin/ld: note: &#39;lrint@@GLIBC_2.4&#39; is defined in DSO /usr/lib/libm.so.6 so try adding it to the linker command line</div>
<div>
		&nbsp;/usr/lib/libm.so.6: could not read symbols: Invalid operation</div>
<div>
		&nbsp;collect2: error: ld returned 1 exit status</div>
</blockquote>
<div>
	由 libm 可见，这是因为数学库没有被包含在编译命令中，于是我们编译&nbsp;<span style="color:#b22222;">build_all.sh</span>，为所有编译命令添加上&nbsp;<span style="color: rgb(255, 0, 0); ">-lm</span>&nbsp;编译参数：<br />
	<span style="color:#0000ff;">The &quot;libm&quot; told me that the math library was not included in the&nbsp;compiling command, so I edited&nbsp;</span><span style="color:#b22222;">build_all.sh</span><span style="color:#0000ff;">&nbsp;and add </span><span style="color:#b22222;">-lm</span><span style="color:#0000ff;"> to all compiling command:&nbsp;</span></div>
<div>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
#!/bin/sh                           

if [ $# -gt 0 ] ; then
        base=`basename $1 .c`
        echo &quot;compiling $base&quot;
        gcc -ggdb `pkg-config opencv --cflags --libs` $base.c -o $base -lm
else
        for i in *.c; do
            echo &quot;compiling $i&quot;
            gcc -ggdb `pkg-config --cflags opencv` -o `basename $i .c` $i `pkg-config --libs opencv` -lm;
        done
        for i in *.cpp; do
            echo &quot;compiling $i&quot;
            g++ -ggdb `pkg-config --cflags opencv` -o `basename $i .cpp` $i `pkg-config --libs opencv` -lm;
        done
fi
</pre>
</div>
<p><span style="color: rgb(255, 255, 255); ">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255); ">http://www.codelast.com/</span></a><br />
还忘了说一句，由于上面的脚本在编译时使用了pkg-config，所以在编译前，我们还需要先安装 pkg-config：<br />
<span style="color:#0000ff;">Sorry, I forget to mention that because of using pkg-config, we need to install pkg-config before compiling the sample:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
pacman -S pkg-config
</pre>
<p>然后再编译，成功。<br />
<span style="color:#0000ff;">Then the compiling will succeed.</span><br />
那么下面，我们再接着尝试把编译出的sample运行起来：<br />
<span style="color:#0000ff;">Then run the executable program we just compiled:</span></p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
[root@alarmpi c]# ./contours 

This program creates an image to demonstrate the use of the &quot;c&quot; contour
functions: cvFindContours() and cvApproxPoly() along with the storage
functions cvCreateMemStorage() and cvDrawContours().
It also shows the use of a trackbar to control contour retrieval.
 
Usage :
./contours
 
(image:460): Gtk-WARNING **: cannot open display:
</pre>
<p>很明显，运行不起来。<br />
看样子是跟gtk相关，并且我在网上搜到这跟X server什么的可能有关系，于是安装gtk和X server：<br />
<span style="color: rgb(0, 0, 255); ">It failed,&nbsp;</span><span style="color:#0000ff;">unfortunately</span><span style="color: rgb(0, 0, 255); ">.</span><br />
<span style="color:#0000ff;">And Google told me that the error is related to X server, too, so I installed gtk &amp; X server:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
pacman -S gtk xorg-server
</pre>
<p>再修改配置文件&nbsp;/etc/ssh/sshd_config ：<br />
<span style="color:#0000ff;">Modify the config file /etc/ssh/sshd_config :</span></p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
#AllowTcpForwarding yes
AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
X11UseLocalhost yes
</pre>
<p>注意，没有注释的那三行是我添加的。<br />
<span style="color:#0000ff;">Note that the 3&nbsp;uncommented lines are added by me.</span><br />
<span style="color: rgb(255, 255, 255); ">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255); ">http://www.codelast.com/</span></a><br />
重启Pi的系统，运行X server：<br />
<span style="color:#0000ff;">Reboot Pi &amp; run X server:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
X
</pre>
<p>没错，命令就是这么简单。然后又出错了：<br />
<span style="color:#0000ff;">Yes, the command is just so simple, but it failed to start:</span></p>
<blockquote>
<div>
		[root@alarmpi c]# X &nbsp; &nbsp; &nbsp;&nbsp;</div>
<div>
		&nbsp;</div>
<div>
		&nbsp;X.Org X Server 1.13.0</div>
<div>
		&nbsp;Release Date: 2012-09-05</div>
<div>
		&nbsp;X Protocol Version 11, Revision 0</div>
<div>
		&nbsp;Build Operating System: Linux 3.0.15-1-ARCH+ armv6l&nbsp;</div>
<div>
		&nbsp;Current Operating System: Linux alarmpi 3.2.27-11-ARCH+ #1 PREEMPT Sat Oct 13 22:46:16 UTC 2012 armv6l</div>
<div>
		&nbsp;Kernel command line: dma.dmachans=0x7f35 bcm2708_fb.fbwidth=1920 bcm2708_fb.fbheight=1080 bcm2708.boardrev=0x3 bcm2708.serial=0x398ca41f smsc95xx.macaddr=B8:27:EB:8C:A4:1F vc_mem.mem_base=0xc000000 vc_mem.mem_size=0x10000000 &nbsp;sdhci-bcm2708.enable_llm=1 sdhci-bcm2708.sync_after_dma=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 loglevel=2 root=/dev/mmcblk0p2 init=/bin/systemd rootfstype=ext4 rootwait</div>
<div>
		&nbsp;Build Date: 14 October 2012 &nbsp;10:05:22PM</div>
<div>
		&nbsp;&nbsp;</div>
<div>
		&nbsp;Current version of pixman: 0.26.2</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>Before reporting problems, check http://wiki.x.org</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>to make sure that you have the latest version.</div>
<div>
		&nbsp;Markers: (--) probed, (**) from config file, (==) default setting,</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>(++) from command line, (!!) notice, (II) informational,</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>(WW) warning, (EE) error, (NI) not implemented, (??) unknown.</div>
<div>
		&nbsp;(==) Log file: &quot;/var/log/Xorg.0.log&quot;, Time: Mon Oct 15 14:30:03 2012</div>
<div>
		&nbsp;(==) Using config directory: &quot;/etc/X11/xorg.conf.d&quot;</div>
<div>
		&nbsp;Initializing built-in extension Generic Event Extension</div>
<div>
		&nbsp;Initializing built-in extension SHAPE</div>
<div>
		&nbsp;Initializing built-in extension MIT-SHM</div>
<div>
		&nbsp;Initializing built-in extension XInputExtension</div>
<div>
		&nbsp;Initializing built-in extension XTEST</div>
<div>
		&nbsp;Initializing built-in extension BIG-REQUESTS</div>
<div>
		&nbsp;Initializing built-in extension SYNC</div>
<div>
		&nbsp;Initializing built-in extension XKEYBOARD</div>
<div>
		&nbsp;Initializing built-in extension XC-MISC</div>
<div>
		&nbsp;Initializing built-in extension SECURITY</div>
<div>
		&nbsp;Initializing built-in extension XINERAMA</div>
<div>
		&nbsp;Initializing built-in extension XFIXES</div>
<div>
		&nbsp;Initializing built-in extension RENDER</div>
<div>
		&nbsp;Initializing built-in extension RANDR</div>
<div>
		&nbsp;Initializing built-in extension COMPOSITE</div>
<div>
		&nbsp;Initializing built-in extension DAMAGE</div>
<div>
		&nbsp;Initializing built-in extension MIT-SCREEN-SAVER</div>
<div>
		&nbsp;Initializing built-in extension DOUBLE-BUFFER</div>
<div>
		&nbsp;Initializing built-in extension RECORD</div>
<div>
		&nbsp;Initializing built-in extension DPMS</div>
<div>
		&nbsp;Initializing built-in extension X-Resource</div>
<div>
		&nbsp;Initializing built-in extension XVideo</div>
<div>
		&nbsp;Initializing built-in extension XVideo-MotionCompensation</div>
<div>
		&nbsp;Initializing built-in extension XFree86-VidModeExtension</div>
<div>
		&nbsp;Initializing built-in extension XFree86-DGA</div>
<div>
		&nbsp;Initializing built-in extension XFree86-DRI</div>
<div>
		&nbsp;Initializing built-in extension DRI2</div>
<div>
		&nbsp;Loading extension GLX</div>
<div>
		&nbsp;</div>
<div>
		&nbsp;Fatal server error:</div>
<div>
		&nbsp;no screens found</div>
<div>
		&nbsp;(EE)&nbsp;</div>
<div>
		&nbsp;Please consult the The X.Org Foundation support&nbsp;</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>&nbsp;at http://wiki.x.org</div>
<div>
		&nbsp; for help.&nbsp;</div>
<div>
		&nbsp;(EE) Please also check the log file at &quot;/var/log/Xorg.0.log&quot; for additional information.</div>
<div>
		&nbsp;(EE)&nbsp;</div>
<div>
		&nbsp;Server terminated with error (1). Closing log file.</div>
</blockquote>
<p>既然它让我看日志文件&nbsp;/var/log/Xorg.0.log，那我就看。在日志文件的最后，发现提示找不到 fbdev 模块/库，于是翻遍Google，找到一个答案：应该安装&nbsp;xf86-video-fbdev 包：<br />
<span style="color:#0000ff;">Since it told me to check log file&nbsp;/var/log/Xorg.0.log, then I did. At the last few lines of the log file, I found an error message which indicated a fbdev module/lib missing, so I ask Google again for a while, and I realized that I should install package&nbsp;xf86-video-fbdev:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
pacman -S xf86-video-fbdev
</pre>
<p><span style="color: rgb(255, 255, 255); ">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255); ">http://www.codelast.com/</span></a><br />
再用&ldquo;X&rdquo;命令启动X server，成功了：<br />
<span style="color:#0000ff;">Then run &quot;X&quot; again, it succeeded:</span></p>
<blockquote>
<div>
		[root@alarmpi ~]# X</div>
<div>
		&nbsp;</div>
<div>
		&nbsp;X.Org X Server 1.13.0</div>
<div>
		&nbsp;Release Date: 2012-09-05</div>
<div>
		&nbsp;X Protocol Version 11, Revision 0</div>
<div>
		&nbsp;Build Operating System: Linux 3.0.15-1-ARCH+ armv6l&nbsp;</div>
<div>
		&nbsp;Current Operating System: Linux alarmpi 3.2.27-11-ARCH+ #1 PREEMPT Sat Oct 13 22:46:16 UTC 2012 armv6l</div>
<div>
		&nbsp;Kernel command line: dma.dmachans=0x7f35 bcm2708_fb.fbwidth=1920 bcm2708_fb.fbheight=1080 bcm2708.boardrev=0x3 bcm2708.serial=0x398ca41f smsc95xx.macaddr=B8:27:EB:8C:A4:1F vc_mem.mem_base=0xc000000 vc_mem.mem_size=0x10000000 &nbsp;sdhci-bcm2708.enable_llm=1 sdhci-bcm2708.sync_after_dma=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 loglevel=2 root=/dev/mmcblk0p2 init=/bin/systemd rootfstype=ext4 rootwait</div>
<div>
		&nbsp;Build Date: 14 October 2012 &nbsp;10:05:22PM</div>
<div>
		&nbsp;&nbsp;</div>
<div>
		&nbsp;Current version of pixman: 0.26.2</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>Before reporting problems, check http://wiki.x.org</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>to make sure that you have the latest version.</div>
<div>
		&nbsp;Markers: (--) probed, (**) from config file, (==) default setting,</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>(++) from command line, (!!) notice, (II) informational,</div>
<div>
		&nbsp;<span class="Apple-tab-span" style="white-space: pre; "> </span>(WW) warning, (EE) error, (NI) not implemented, (??) unknown.</div>
<div>
		&nbsp;(==) Log file: &quot;/var/log/Xorg.0.log&quot;, Time: Mon Oct 15 14:32:34 2012</div>
<div>
		&nbsp;(==) Using config directory: &quot;/etc/X11/xorg.conf.d&quot;</div>
<div>
		&nbsp;Initializing built-in extension Generic Event Extension</div>
<div>
		&nbsp;Initializing built-in extension SHAPE</div>
<div>
		&nbsp;Initializing built-in extension MIT-SHM</div>
<div>
		&nbsp;Initializing built-in extension XInputExtension</div>
<div>
		&nbsp;Initializing built-in extension XTEST</div>
<div>
		&nbsp;Initializing built-in extension BIG-REQUESTS</div>
<div>
		&nbsp;Initializing built-in extension SYNC</div>
<div>
		&nbsp;Initializing built-in extension XKEYBOARD</div>
<div>
		&nbsp;Initializing built-in extension XC-MISC</div>
<div>
		&nbsp;Initializing built-in extension SECURITY</div>
<div>
		&nbsp;Initializing built-in extension XINERAMA</div>
<div>
		&nbsp;Initializing built-in extension XFIXES</div>
<div>
		&nbsp;Initializing built-in extension RENDER</div>
<div>
		&nbsp;Initializing built-in extension RANDR</div>
<div>
		&nbsp;Initializing built-in extension COMPOSITE</div>
<div>
		&nbsp;Initializing built-in extension DAMAGE</div>
<div>
		&nbsp;Initializing built-in extension MIT-SCREEN-SAVER</div>
<div>
		&nbsp;Initializing built-in extension DOUBLE-BUFFER</div>
<div>
		&nbsp;Initializing built-in extension RECORD</div>
<div>
		&nbsp;Initializing built-in extension DPMS</div>
<div>
		&nbsp;Initializing built-in extension X-Resource</div>
<div>
		&nbsp;Initializing built-in extension XVideo</div>
<div>
		&nbsp;Initializing built-in extension XVideo-MotionCompensation</div>
<div>
		&nbsp;Initializing built-in extension XFree86-VidModeExtension</div>
<div>
		&nbsp;Initializing built-in extension XFree86-DGA</div>
<div>
		&nbsp;Initializing built-in extension XFree86-DRI</div>
<div>
		&nbsp;Initializing built-in extension DRI2</div>
<div>
		&nbsp;Loading extension GLX</div>
</blockquote>
<p><span style="color: rgb(255, 255, 255); ">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255); ">http://www.codelast.com/</span></a><br />
再试着运行OpenCV的sample，依然不行，Google搜索到一篇<a href="http://homebrew.jp/show?page=1440" target="_blank" rel="noopener noreferrer">在Pi上运行OpenCV的文章</a>，作者做了这样一件事情：<br />
<span style="color:#0000ff;">Then I tried to run the OpenCV sample again, still the same error(&quot;cannot open display&quot;), so I Googled </span><a href="http://homebrew.jp/show?page=1440" target="_blank" rel="noopener noreferrer"><span style="color:#0000ff;"><span style="background-color:#ffa07a;">another article about using OpenCV on Pi</span></span></a><span style="color:#0000ff;">&nbsp;and found that the author did one thing:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;" style="width: 729px; ">
export DISPLAY=192.168.3.65:0.0
</pre>
<p>其中，192.168.3.65是Pi的IP地址。这样设置之后，再运行，程序不再报错了！再一看相同的目录下，生成了一个&nbsp;contours.xml 文件，说明程序执行成功了。<br />
<span style="color:#0000ff;">In which the &quot;192.168.3.65&quot; is your Pi&#39;s IP address. After setting this, the sample could run without any error&nbsp;occurred, and a contours.xml file was generated under the same directory, which indicated that we succeeded.</span></p>
<p><span style="background-color:#00ff00;">【4】</span>写一个简单的OpenCV C程序 / Write a simple OpenCV C program<br />
现在该写一个简单的OpenCV C程序来控制摄像头了。<br />
<span style="color:#0000ff;">Now we should write a simple C program to control the webcam by using OpenCV.</span></p>
<p>直接看程序：<br />
<span style="color:#0000ff;">Let&#39;s check the C code:</span></p>
<pre class="brush:cpp;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &quot;highgui.h&quot;
#include &quot;opencv.hpp&quot;

int main(int argc, char **argv) {
	/* init camera */
	CvCapture* pCapture = cvCreateCameraCapture(0);
	cvSetCaptureProperty(pCapture, CV_CAP_PROP_FRAME_WIDTH, 320); 
	cvSetCaptureProperty(pCapture, CV_CAP_PROP_FRAME_HEIGHT, 240);
	//cvSetCaptureProperty(pCapture, CV_CAP_PROP_FPS, 5);

	IplImage *pFrame = 0;

	if (NULL == pCapture) {
		fprintf(stderr, &quot;Can&#39;t initialize webcam!\n&quot;);
		return 1;
	}

	pFrame = cvQueryFrame(pCapture);	// query a frame 

	if(NULL == pFrame) {
		fprintf(stderr, &quot;Can&#39;t get a frame!\n&quot; );
		return 1;
	}

	const char *pImageFileName = &quot;webcam.jpg&quot;;
	cvSaveImage(pImageFileName, pFrame);

	cvReleaseCapture(&amp;pCapture);	// free memory

	return 0;
}
</pre>
<p>此程序做的事情非常简单：初始化摄像头，抓取一帧，然后保存为名为&ldquo;webcam.jpg&rdquo;的图片。<br />
<span style="color:#0000ff;">This program does a very simple job: initialize the camera, capture a frame &amp; save it to a image file named &quot;webcam.jpg&quot;.</span><br />
<span style="color: rgb(255, 255, 255); ">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255); ">http://www.codelast.com/</span></a><br />
编译自己的webcam程序：<br />
<span style="color:#0000ff;">Then compile the webcam program:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
g++ -I/usr/include/opencv/ -I/usr/include/opencv2/  `pkg-config --cflags opencv --libs opencv` webcam.c -o webcam
</pre>
<p>会生成一个可执行程序&ldquo;webcam&rdquo;，运行它：<br />
<span style="color:#0000ff;">This will generate an executable bin &quot;webcam&quot;, just run it:</span></p>
<pre class="brush:shell;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
./webcam
</pre>
<p>然后在相同目录下，会看到生成了一个&ldquo;webcam.jpg&rdquo;图片，正是摄像头拍的照。<br />
<span style="color:#0000ff;">Then we&#39;ll get a &quot;webcam.jpg&quot; image file under the same directory, which is just the photo took by the camera.</span></p>
<p>这样，本文的主要目的就达成了。可以在此基础上继续开发其他的程序，来实现更为有用的功能，例如像<a href="http://www.codelast.com/?p=4341" target="_blank" rel="noopener noreferrer">摄像头娘</a>一样的运动检测功能。<br />
<span style="color:#0000ff;">So the main&nbsp;purpose of this article has been reached. We can develop more useful programs base on it, e.g. a program similar to the </span><a href="http://www.codelast.com/?p=4341" target="_blank" rel="noopener noreferrer"><span style="color:#0000ff;"><span style="background-color:#ffa07a;">Camera Girl</span></span></a><span style="color:#0000ff;">, which implements the motion detection&nbsp;functionality.</span><br />
<span style="color: rgb(255, 255, 255); ">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255); ">http://www.codelast.com/</span></a><br />
<span style="background-color:#00ff00;">【5】</span>遗留问题 <span style="color:#ff0000;">/</span>&nbsp;<span style="color:#0000ff;">Unsolved problems</span><br />
在上述过程中，其实我还遇到了一些未解决的问题，暂时没有时间深究，在此先记录如下。<br />
<span style="color:#0000ff;">In the above process I met some unsolved problems and have no time to explore them yet, so I just write them down here for further study.</span></p>
<p><span style="background-color:#ee82ee;">①</span>拍照时使用稍高的分辨率就导致程序崩溃 <span style="color:#ff0000;">/</span> <span style="color:#0000ff;">Use a little high resolution will cause the program crash</span><br />
在上面的程序中，如下两句是用于设置分辨率的（宽*高）：<br />
<span style="color:#0000ff;">In the above codes, the two lines below are used to set the resolution:</span></p>
<pre class="brush:cpp;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
cvSetCaptureProperty(pCapture, CV_CAP_PROP_FRAME_WIDTH, 320); 
cvSetCaptureProperty(pCapture, CV_CAP_PROP_FRAME_HEIGHT, 240);
</pre>
<p>根据我的试验，160*120的低分辨率比较少出问题，尽管320*240的分辨率对摄像头来说也根本不算高的，但是就算是使用320*240的分辨率，程序还是偶尔会崩溃的，报错如下：<br />
<span style="color:#0000ff;">According to my experiments, the 160*120 low resolution cause less crashes than higher resolutions. Even 320*240 is not a high resolution for a webcam nowadays, it still made the program crashed some times, and the error messages are:</span></p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
[root@alarmpi c]# ./webcam 
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_QUERYMENU: Invalid argument
VIDIOC_REQBUFS: Cannot allocate memory
munmap: Invalid argument
munmap: Invalid argument
munmap: Invalid argument
munmap: Invalid argument
Unable to stop the stream.: Bad file descriptor
munmap: Invalid argument
munmap: Invalid argument
munmap: Invalid argument
munmap: Invalid argument
HIGHGUI ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.
Can&#39;t get a frame!
</pre>
<p><span style="color: rgb(255, 255, 255); ">文章来源：</span><a href="http://www.codelast.com/" target="_blank" rel="noopener noreferrer"><span style="color: rgb(255, 255, 255); ">http://www.codelast.com/</span></a><br />
或者：<br />
<span style="color:#0000ff;">Or:</span></p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
VIDIOC_REQBUFS: Cannot allocate memory
HIGHGUI ERROR: V4L/V4L2: Could not obtain specifics of capture window.

Unable to stop the stream.: Bad file descriptor
VIDIOC_QBUF: Bad file descriptor
Can&#39;t get a frame!
</pre>
<p>我不确定这是跟Pi的CPU计算能力较弱有关呢，还是跟Pi的RAM太小有关呢，还是跟摄像头的供电不足有关呢（我没有使用带电源的USB HUB来接摄像头），或者是跟摄像头的驱动有关呢？<br />
如果你知道解决办法，请赐教，非常感谢。<br />
<span style="color:#0000ff;">I&#39;m not sure whether the problem is caused by the weak computation capability of Pi&#39;s CPU, or the too-small RAM on Pi, or the&nbsp;insufficient current supply of the webcam(I didn&#39;t use a powered USB HUB to connect the webcam to Pi), or the webcam&#39;s Linux driver...<br />
If you know something, please tell me and thank you&nbsp;in advance.</span></p>
<p><span style="background-color: rgb(238, 130, 238);">2015-02-19更新：</span><br />
在树莓派model B+上，使用OpenCV 2.4.10版的上述程序，已经没有了上面所说的问题，经我测试，每隔2秒一次，连续抓取了将近30分钟的图像，一次都没有问题。</p>
<p><span style="color: rgb(255, 255, 255);">文章来源：</span><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><span style="color: rgb(255, 255, 255);">https://www.codelast.com/</span></a><br />
<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;版权声明&nbsp;<span style="color: rgb(255, 0, 0);">➤➤</span>&nbsp;<br />
转载需注明出处：<u><a href="https://www.codelast.com/" rel="noopener noreferrer" target="_blank"><em><span style="color: rgb(0, 0, 255);"><strong style="font-size: 16px;"><span style="font-family: arial, helvetica, sans-serif;">codelast.com</span></strong></span></em></a></u>&nbsp;<br />
感谢关注我的微信公众号（微信扫一扫）：</p>
<p style="border: 0px; font-size: 13px; margin: 0px 0px 9px; outline: 0px; padding: 0px; color: rgb(77, 77, 77);">
	<img decoding="async" alt="wechat qrcode of codelast" src="https://www.codelast.com/codelast_wechat_qr_code.jpg" style="width: 200px; height: 200px;" /></p>
<div id="KSFIND_MASK" style="background-color: rgb(0, 0, 0); opacity: 0.22; position: absolute !important; left: 0px !important; top: 0px !important; border: 0px none !important; padding: 0px !important; z-index: 1000000 !important; height: 0px; width: 0px; display: none; ">
	&nbsp;</div>

			<!--[syntaxhighlighter]-->
			<!--代码高亮，请勿编辑-->
			<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shCore.js"></script><script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushShell.js"></script>
<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushPlain.js"></script>
<script type="text/javascript" src="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/scripts/shBrushCpp.js"></script>

			<link type="text/css" rel="stylesheet" href="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/styles/shCoreCk.css" />
			<link type="text/css" rel="stylesheet" href="https://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/syntaxhighlighter/styles/shThemeCk.css" />
			<script type="text/javascript">
			SyntaxHighlighter.defaults['class-name']	= '';
			SyntaxHighlighter.defaults['smart-tabs']	= true;
			SyntaxHighlighter.defaults['tab-size']		= 2;
			SyntaxHighlighter.defaults['gutter']		= true;
			SyntaxHighlighter.defaults['quick-code']	= true;
			SyntaxHighlighter.defaults['collapse'] 		= false;
			SyntaxHighlighter.defaults['auto-links']	= true;
			SyntaxHighlighter.defaults['toolbar']		= true;
			SyntaxHighlighter.all();
			</script>
			<!--[/syntaxhighlighter]-->]]></content:encoded>
					
					<wfw:commentRss>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e5%9c%a8raspberry-pi%e4%b8%8a%e7%94%a8opencv%e6%9d%a5%e6%93%8d%e7%ba%b5%e6%91%84%e5%83%8f%e5%a4%b4%e6%8b%8d%e7%85%a7use-opencv-on-raspberry-pi-to-controll-a-webcam-to-take-photos/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
	</channel>
</rss>
