<?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>OpenCV &#8211; 编码无悔 /  Intent &amp; Focused</title>
	<atom:link href="https://www.codelast.com/tag/opencv/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.codelast.com</link>
	<description>最优化之路</description>
	<lastBuildDate>Sun, 03 May 2020 12:33:52 +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>[原创] 解决ELL demo的 OpenCV Error: Unspecified error in cvShowImage 错误</title>
		<link>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e8%a7%a3%e5%86%b3ell-demo%e7%9a%84-opencv-error-unspecified-error-in-cvshowimage-%e9%94%99%e8%af%af/</link>
					<comments>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e8%a7%a3%e5%86%b3ell-demo%e7%9a%84-opencv-error-unspecified-error-in-cvshowimage-%e9%94%99%e8%af%af/#respond</comments>
		
		<dc:creator><![CDATA[learnhard]]></dc:creator>
		<pubDate>Mon, 17 Jul 2017 16:17:36 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[ELL]]></category>
		<category><![CDATA[libgtk2.0-dev]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[Unspecified error in cvShowImage]]></category>
		<guid isPermaLink="false">https://www.codelast.com/?p=9473</guid>

					<description><![CDATA[<p>
OS：Ubuntu 14.04 LTS</p>
<p>在<a href="https://github.com/Microsoft/ELL" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">ELL</span></a>的<a href="https://github.com/Microsoft/ELL/blob/master/tutorials/vision/gettingStarted/cntk.md" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">tutorial</span></a>中，有一个步骤是在PC上测试运行一个demo程序来检查ELL能否正常工作，当你选择CNTK model的时候，运行的就是 <span style="color:#0000ff;">cntkDemo.py</span> 这个demo程序。<br />
<span id="more-9473"></span><br />
这个demo程序调用了OpenCV来在GUI窗口中显示摄像头拍摄的实时视频，可能会跑不起来，并输出下面这样的错误：</p>
<blockquote>
<p>
		OpenCV Error: Unspecified error (The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script) in cvShowImage, file /feedstock_root/build_artefacts/opencv_1490907195496/work/opencv-3.2.0/modules/highgui/src/window.cpp,</p></blockquote>&#8230; <a href="https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e8%a7%a3%e5%86%b3ell-demo%e7%9a%84-opencv-error-unspecified-error-in-cvshowimage-%e9%94%99%e8%af%af/" class="read-more">Read More </a>]]></description>
										<content:encoded><![CDATA[<p>
OS：Ubuntu 14.04 LTS</p>
<p>在<a href="https://github.com/Microsoft/ELL" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">ELL</span></a>的<a href="https://github.com/Microsoft/ELL/blob/master/tutorials/vision/gettingStarted/cntk.md" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">tutorial</span></a>中，有一个步骤是在PC上测试运行一个demo程序来检查ELL能否正常工作，当你选择CNTK model的时候，运行的就是 <span style="color:#0000ff;">cntkDemo.py</span> 这个demo程序。<br />
<span id="more-9473"></span><br />
这个demo程序调用了OpenCV来在GUI窗口中显示摄像头拍摄的实时视频，可能会跑不起来，并输出下面这样的错误：</p>
<blockquote>
<p>
		OpenCV Error: Unspecified error (The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script) in cvShowImage, file /feedstock_root/build_artefacts/opencv_1490907195496/work/opencv-3.2.0/modules/highgui/src/window.cpp, ...（后面还有很长的内容）</p>
</blockquote>
<p>如果你的PC和我的一样老旧，那么执行 <span style="color:#0000ff;">python cntkDemo.py</span> 可能耗时非常长（你可以在一台老爷车上试一下），直到N分钟后才打印出上面的错误，然后程序挂掉，这使得我们解决这个问题非常不方便&mdash;&mdash;每次都要等待超级长的时间，才知道自己的修改是否有效。<br />
<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 />
因此，为了能便于debug问题，我们先把和上面那个错误相关的关键代码段提取出来，单独放到一个源代码文件 z.py 中：</p>
<section class="output_wrapper" id="output_wrapper_id" style="font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; letter-spacing: 0px; font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, Arial, sans-serif;">
<pre style="font-size: inherit; color: inherit; line-height: inherit; margin-top: 0px; margin-bottom: 0px; padding: 0px;">
<code class="python language-python hljs" style="margin: 0px 2px; line-height: 18px; font-size: 14px; letter-spacing: 0px; font-family: Consolas, Inconsolata, Courier, monospace; border-radius: 0px; color: rgb(169, 183, 198); background: rgb(40, 43, 46); padding: 0.5em; overflow-wrap: normal !important; word-break: normal !important; overflow: auto !important; display: -webkit-box !important;"><span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(248, 35, 117); word-wrap: inherit !important; word-break: inherit !important;">import</span>&nbsp;numpy&nbsp;<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(248, 35, 117); word-wrap: inherit !important; word-break: inherit !important;">as</span>&nbsp;np
<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(248, 35, 117); word-wrap: inherit !important; word-break: inherit !important;">import</span>&nbsp;cv2
cam&nbsp;=&nbsp;cv2.VideoCapture(<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(174, 135, 250); word-wrap: inherit !important; word-break: inherit !important;">0</span>)
<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(248, 35, 117); word-wrap: inherit !important; word-break: inherit !important;">while</span>&nbsp;<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(248, 35, 117); word-wrap: inherit !important; word-break: inherit !important;">True</span>:
&nbsp;&nbsp;&nbsp;&nbsp;ret,&nbsp;frame&nbsp;=&nbsp;cam.read()
&nbsp;&nbsp;&nbsp;&nbsp;cv2.imshow(<span class="hljs-string" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(238, 220, 112); word-wrap: inherit !important; word-break: inherit !important;">&#39;test&#39;</span>,&nbsp;frame)
&nbsp;&nbsp;&nbsp;&nbsp;<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(248, 35, 117); word-wrap: inherit !important; word-break: inherit !important;">if</span>&nbsp;cv2.waitKey(<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(174, 135, 250); word-wrap: inherit !important; word-break: inherit !important;">1</span>)&nbsp;&amp;&nbsp;<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(174, 135, 250); word-wrap: inherit !important; word-break: inherit !important;">0xFF</span>&nbsp;==&nbsp;<span class="hljs-number" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(174, 135, 250); word-wrap: inherit !important; word-break: inherit !important;">27</span>:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="hljs-keyword" style="font-size: inherit; line-height: inherit; margin: 0px; padding: 0px; color: rgb(248, 35, 117); word-wrap: inherit !important; word-break: inherit !important;">break</span></code></pre>
</section>
<p>稍后，我们只需要执行 <span style="color:#0000ff;">python z.py</span>，不出错的话，就说明我们搞定了以上问题。<br />
注意：这里的程序假设你的Ubuntu PC上至少连接了一个USB摄像头，cv2.VideoCapture(0)里的0就是指第一个摄像头，千万不要傻傻地在没有摄像头的情况下测试。<br />
<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></p>
<div>
	其实，打印出的错误信息已经告诉我们，如果你使用的是Ubuntu，需要安装&nbsp;<span style="color:#0000ff;">libgtk2.0-dev</span> 和 <span style="color:#0000ff;">pkg-config</span>，然后rebuild软件。这里没有写清楚到底是rebuild OpenCV还是ELL，但我理解应该是指OpenCV。不过根据我的试验，把系统里的OpenCV卸载掉，并且把miniconda环境里的OpenCV也卸载掉，然后安装&nbsp;libgtk2.0-dev 和 pkg-config，再按ELL doc的方法把miniconda环境里的OpenCV装上，并不能fix这个问题。<br />
	经过漫长的Google搜索，我最终找到了问题的原因：ELL文档中提供的安装opencv的方法有问题（至少在我的Ubuntu上如此）：</div>
<blockquote>
<div>
		conda install -c conda-forge opencv</div>
</blockquote>
<div>
	这样安装上的OpenCV，在运行<span style="color:#0000ff;">&nbsp;cntkDemo.py</span> 的时候就会出上面的错。</div>
<div>
	&nbsp;</div>
<div>
	我在Stack Overflow上找到的一个解决方案是，你应该在conda环境下，用下面的方法来安装OpenCV：</div>
<blockquote>
<div>
		conda install --channel loopbio --channel conda-forge --channel pkgw-forge gtk2 ffmpeg ffmpeg-feature gtk2-feature opencv</div>
</blockquote>
<div>
	这样安装好了OpenCV之后，再运行 python z.py，你就会看到它神奇地解决了问题：马上弹出了一个图形窗口，里面显示的就是摄像头拍摄的实时视频。<br />
	当然，在安装之前，如果已经装错了另一个版本的OpenCV，需要先用 <span style="color:#0000ff;">conda remove opencv</span> 卸载掉。关于这个错误的详解可以看<a href="https://stackoverflow.com/questions/40207011/opencv-not-working-properly-with-python-on-linux-with-anaconda-getting-error-th" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">这个</span></a>和<a href="https://github.com/conda-forge/opencv-feedstock/issues/43" rel="noopener noreferrer" target="_blank"><span style="background-color:#ffa07a;">这个</span></a>链接。<br />
	<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>
]]></content:encoded>
					
					<wfw:commentRss>https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e8%a7%a3%e5%86%b3ell-demo%e7%9a%84-opencv-error-unspecified-error-in-cvshowimage-%e9%94%99%e8%af%af/feed/</wfw:commentRss>
			<slash:comments>0</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>
		<item>
		<title>[原创]摄像头娘来了</title>
		<link>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e6%91%84%e5%83%8f%e5%a4%b4%e5%a8%98%e6%9d%a5%e4%ba%86/</link>
					<comments>https://www.codelast.com/%e5%8e%9f%e5%88%9b%e6%91%84%e5%83%8f%e5%a4%b4%e5%a8%98%e6%9d%a5%e4%ba%86/#comments</comments>
		
		<dc:creator><![CDATA[learnhard]]></dc:creator>
		<pubDate>Fri, 27 Jan 2012 18:07:31 +0000</pubDate>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[原创]]></category>
		<category><![CDATA[综合]]></category>
		<category><![CDATA[motion detection]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[t.qq.com/cameragirl]]></category>
		<category><![CDATA[VC++发微博]]></category>
		<category><![CDATA[VC++运动检测]]></category>
		<category><![CDATA[代码]]></category>
		<category><![CDATA[内存泄漏]]></category>
		<category><![CDATA[微博]]></category>
		<category><![CDATA[微博API]]></category>
		<category><![CDATA[摄像头娘]]></category>
		<category><![CDATA[物联网]]></category>
		<category><![CDATA[萌娘]]></category>
		<category><![CDATA[运动检测]]></category>
		<category><![CDATA[饮水机娘]]></category>
		<guid isPermaLink="false">http://www.codelast.com/?p=4341</guid>

					<description><![CDATA[<p>
被标题吸引进来的各位，抱歉，这还是一篇技术文章<img decoding="async" alt="crying" height="24" src="http://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/ckeditor/plugins/smiley/images/14.gif" title="crying" width="24" /><br />
本文的主角是一个摄像头及其配套程序，我毫无创意地模仿网上的流行说法，称之为&#8220;<span style="color:#ff0000;">摄像头娘</span>&#8221;。她会自己发微博，<span style="color:#0000ff;">记得follow她哦</span>：<strong><a href="http://t.qq.com/cameragirl" target="_blank" rel="noopener noreferrer"><span style="color:#ff0000;"><span style="background-color:#99ff99;">t.qq.com/cameragirl</span></span></a></strong></p>
<p>前段时间浙大有个博士做了个&#8220;<span style="color:#800080;">饮水机娘</span>&#8221;，也就是他实验室里的饮水机没水或者水加热开了的时候，都会自动发一条微博。这个与&#8220;物联网&#8221;扯上了关系的东西，让我原来以为那位博士是改造了饮水机，加上了温度及水位传感器，配合单片机，将饮水机的状态采集到PC中去，再写一个PC上的软件将触发的事件发送到微博上，后来看了相关的介绍，才知道没那么复杂，其实他没有改造饮水机，而是用一个摄像头对准饮水机的状态指示灯，根据指示灯的情况，来判断饮水机的状态。</p>
<p>于是我也就萌生了做一个&#8220;摄像头娘&#8221;的念头。<br />
我构想中的&#8220;摄像头娘&#8221;是这样的：当有物体在她面前运动的时候，她能感受得到，并且会为这个过客拍一张照片，然后发到微博上。<br />
下面是<span style="color:#ff0000;">实际效果截图</span>：<br />
<span id="more-4341"></span></p>
<div style="text-align: center; ">
	<a href="http://t.qq.com/cameragirl" target="_blank" rel="noopener noreferrer"><img decoding="async" alt="" src="http://www.codelast.com/wp-content/uploads/2012/01/weibo_snapshot.png" style="width: 542px; height: 330px; " /></a></div>
<p>好吧，说得傻一点就是：一个有运动检测（motion detection）功能的程序，当检测到摄像头前有物体在运动时，就将画面拍一张照片，发到微博上。<br />
确实，没啥创意，但是还是有一定实用性的。例如，你可以在家里放置一个&#8220;她&#8221;为你看家，假设你运气不好，有不速之客闯进了你家里，那么，只要他进入了&#8220;摄像头娘&#8221;的视角，就会马上被检测到，然后被拍上来，发到微博上，后面的事，哼哼，你就有第一手证据了。<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="color:#0000ff;">VC++ 2005</span>开发的这个软件，运行于Win7上，其实它很简单，功能主要分为两部分：运动检测（motion detection）&#38; 发微博，下面分别陈述。<br />
<span style="background-color:#afeeee;">【1】</span>运动检测 / motion detection<br />
从头自己写？那得多笨才能这样做啊！而且我也不是干视频处理这一行的，一时半会写不出来这玩意。<br />
久闻<a href="http://opencv.willowgarage.com/wiki/" target="_blank" rel="noopener noreferrer"><span style="background-color:#faebd7;">OpenCV</span></a>的大名，我知道它可以帮我实现想要的功能，所以毫不犹豫地选择了它。<br />
我以前也从未使用过OpenCV，从下载它的开发包开始，到参照网上的demo写出一个可用的motion detection程序，只花了半天多时间，由此可见OpenCV的强大。<br />
关于OpenCV的介绍，这里只摘取其官网的一句话：</p>
<blockquote>
<p>
		OpenCV (Open Source Computer Vision) is a library of programming functions for real time computer vision.</p></blockquote>&#8230; <a href="https://www.codelast.com/%e5%8e%9f%e5%88%9b%e6%91%84%e5%83%8f%e5%a4%b4%e5%a8%98%e6%9d%a5%e4%ba%86/" class="read-more">Read More </a>]]></description>
										<content:encoded><![CDATA[<p>
被标题吸引进来的各位，抱歉，这还是一篇技术文章<img decoding="async" alt="crying" height="24" src="http://www.codelast.com/wp-content/plugins/ck-and-syntaxhighlighter/ckeditor/plugins/smiley/images/14.gif" title="crying" width="24" /><br />
本文的主角是一个摄像头及其配套程序，我毫无创意地模仿网上的流行说法，称之为&ldquo;<span style="color:#ff0000;">摄像头娘</span>&rdquo;。她会自己发微博，<span style="color:#0000ff;">记得follow她哦</span>：<strong><a href="http://t.qq.com/cameragirl" target="_blank" rel="noopener noreferrer"><span style="color:#ff0000;"><span style="background-color:#99ff99;">t.qq.com/cameragirl</span></span></a></strong></p>
<p>前段时间浙大有个博士做了个&ldquo;<span style="color:#800080;">饮水机娘</span>&rdquo;，也就是他实验室里的饮水机没水或者水加热开了的时候，都会自动发一条微博。这个与&ldquo;物联网&rdquo;扯上了关系的东西，让我原来以为那位博士是改造了饮水机，加上了温度及水位传感器，配合单片机，将饮水机的状态采集到PC中去，再写一个PC上的软件将触发的事件发送到微博上，后来看了相关的介绍，才知道没那么复杂，其实他没有改造饮水机，而是用一个摄像头对准饮水机的状态指示灯，根据指示灯的情况，来判断饮水机的状态。</p>
<p>于是我也就萌生了做一个&ldquo;摄像头娘&rdquo;的念头。<br />
我构想中的&ldquo;摄像头娘&rdquo;是这样的：当有物体在她面前运动的时候，她能感受得到，并且会为这个过客拍一张照片，然后发到微博上。<br />
下面是<span style="color:#ff0000;">实际效果截图</span>：<br />
<span id="more-4341"></span></p>
<div style="text-align: center; ">
	<a href="http://t.qq.com/cameragirl" target="_blank" rel="noopener noreferrer"><img decoding="async" alt="" src="http://www.codelast.com/wp-content/uploads/2012/01/weibo_snapshot.png" style="width: 542px; height: 330px; " /></a></div>
<p>好吧，说得傻一点就是：一个有运动检测（motion detection）功能的程序，当检测到摄像头前有物体在运动时，就将画面拍一张照片，发到微博上。<br />
确实，没啥创意，但是还是有一定实用性的。例如，你可以在家里放置一个&ldquo;她&rdquo;为你看家，假设你运气不好，有不速之客闯进了你家里，那么，只要他进入了&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="color:#0000ff;">VC++ 2005</span>开发的这个软件，运行于Win7上，其实它很简单，功能主要分为两部分：运动检测（motion detection）&amp; 发微博，下面分别陈述。<br />
<span style="background-color:#afeeee;">【1】</span>运动检测 / motion detection<br />
从头自己写？那得多笨才能这样做啊！而且我也不是干视频处理这一行的，一时半会写不出来这玩意。<br />
久闻<a href="http://opencv.willowgarage.com/wiki/" target="_blank" rel="noopener noreferrer"><span style="background-color:#faebd7;">OpenCV</span></a>的大名，我知道它可以帮我实现想要的功能，所以毫不犹豫地选择了它。<br />
我以前也从未使用过OpenCV，从下载它的开发包开始，到参照网上的demo写出一个可用的motion detection程序，只花了半天多时间，由此可见OpenCV的强大。<br />
关于OpenCV的介绍，这里只摘取其官网的一句话：</p>
<blockquote>
<p>
		OpenCV (Open Source Computer Vision) is a library of programming functions for real time computer vision.</p>
</blockquote>
<p>没错，大名鼎鼎的机器视觉开发库。<br />
我使用的版本是2.3.1，下载回来之后会看到，它里面已经没有VC++2005的lib了，只有2008及2010的（2005确实太老了），但是试验之后会发现，在VC++ 2005中用2008的lib完全没问题。<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="color:#0000cd;">获取摄像头的视频流&rarr;在很短的时间内连续抓取两帧图像&rarr;计算两幅图像的差值&rarr;计算直方图&rarr;判断某些指标是否超过了阈值&rarr;触发动作</span>。我没有图像处理的编码经验，所以也只能解释到这个业余的水平了。<br />
这种功能的代码在网上比比皆是，不过，很多都有陷阱：内存泄漏。基本上来说，都是错误使用cvCloneImage函数造成的。此函数如果放在一个循环中，会导致一次吃掉几M内存（对分辨率不高的图像来说），就算使用了cvReleaseImage函数来释放内存，似乎也没用&mdash;&mdash;应该是对OpenCV的熟悉度不足造成的，用法不对。网上一搜索，就会发现无数人都遇到了这样的问题，那些一篇又一篇的转载文章几乎都是说用同一种方法：以cvCopy来代替cvCloneImage实现同样的功能。<br />
我就是用这种方法解决了内存泄漏问题的，不过，在换成cvCopy之后还有许多其他的问题，一言难尽，看我下面的代码就知道正确的做法了。总之一句话：通过不断Google是可以搞定的这些问题的。<br />
下面，就来看看motion detection的核心代码吧（使用的OpenCV库文件为&nbsp;<span style="color:#008080;">opencv_core231.lib</span>，<span style="color:#008080;">opencv_highgui231.lib</span>，<span style="color:#008080;">opencv_imgproc231.lib</span>）：</p>
<pre class="brush:cpp;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
/**
 * Author: Darran Zhang @ codelast.com
 * Date: 2012-01-27
 */

CvCapture* pCapture = cvCreateCameraCapture(0);  // 初始化摄像头 

if(NULL == pCapture) {
  MessageBox(_T(&quot;检测不到摄像头！&quot;), _T(&quot;错误&quot;), MB_ICONERROR);
  return;
}

string strCameraWindowName = &quot;摄像头&quot;;   // 窗口标题 
string strDiffWindowName = &quot;图像差值&quot;;   // 窗口标题 
cvNamedWindow(strCameraWindowName.c_str(), CV_WINDOW_AUTOSIZE); // 创建一个窗口，第二个参数使得用户不能手动改变窗口大小 
cvNamedWindow(strDiffWindowName.c_str(), CV_WINDOW_AUTOSIZE);

IplImage *pFrame = cvQueryFrame(pCapture);      // 随意获取一帧，这是为了通过这一帧取到其宽、高、像素位深、通道数，否则就无法正确创建其他帧图像 
IplImage *pFrameA = NULL;                       // 其中一帧 
IplImage *pFrameB = cvCreateImage(cvSize(pFrame-&gt;width, pFrame-&gt;height), pFrame-&gt;depth, pFrame-&gt;nChannels);     // 其中一帧 
IplImage *pFrameSub = cvCloneImage(pFrameB);    // A、B帧相减之后的帧 

int nDims = 256;     // 划分HIST的个数，越高越精确 
float hRangesArr[] = {0, 255};
float* hRanges = hRangesArr;

IplImage *pGrayscaleImage = NULL;  // 灰度图 
CvHistogram *pHist = cvCreateHist(1, &amp;nDims, CV_HIST_ARRAY, &amp;hRanges, 1);   // 创建直方图 
float fMaxValue = 0.0;

time_t ts = 0;   // 记录时间戳，用于防止在1秒内多次触发运动检测事件 

m_bActive = true;
while(m_bActive)
{
  pFrameA = cvQueryFrame(pCapture);  // 注意：cvQueryFrame返回的指针总是指向同一块内存 
  if(!pFrameA) {
    m_stcSD.strLatestErrMsg = _T(&quot;无法抓取视频帧&quot;);
    SendStatDataUpdateMsg();

    break;
  }

  cvAbsDiff(pFrameB, pFrameA, pFrameSub); // 计算两幅图像之差 
  cvCopy(pFrameA, pFrameB);               // 拷贝图像，第一个参数为源，第二个参数为目标 

  /* 显示摄像头图像 */
  cvMoveWindow(strCameraWindowName.c_str(), 150, 50);   // 设定窗口位置(x，y坐标) 
  cvShowImage(strCameraWindowName.c_str(), pFrameB);    // 显示图像，第2个参数指定了要显示的图像 

  /* 显示差值图像 */
  cvMoveWindow(strDiffWindowName.c_str(), 150, 400);
  cvShowImage(strDiffWindowName.c_str(), pFrameSub);

  /* 转换图像并计算直方图 */
  pGrayscaleImage = cvCreateImage(cvGetSize(pFrameSub), IPL_DEPTH_8U, 1);   // 创建灰度图 
  cvCvtColor(pFrameSub, pGrayscaleImage, CV_BGR2GRAY);                      // 将彩色图像转换为灰阶图像 
  cvCalcHist(&amp;pGrayscaleImage, pHist, 0, 0);                                // 计算直方图 

  /* 判断阈值是否超限，若超限则触发动作 */
  fMaxValue = 0.0;
  cvGetMinMaxHistValue(pHist, 0, &amp;fMaxValue, 0, 0);  // 找最大值，保存到fMaxValue中，第2个参数是最小值，不过我们不用 
  cvConvertScale(pHist-&gt;bins, pHist-&gt;bins, (fMaxValue ? (255.0 / fMaxValue) : 0.0), 0); // 缩放 bin 到区间 [0, 255] 

  double dRealtimeVal = cvGetReal1D(pHist-&gt;bins, 10);
  if (dRealtimeVal &gt; m_dDetectThreshold) {    // 判断是否大于预先设定的阈值 
    CTime ct = CTime::GetCurrentTime();
    time_t tsRef = ct.GetTime();
    if (tsRef - ts &gt;= 1) {
	  //TODO: 在此触发动作 
      ts = tsRef;
    }
  }

  cvReleaseImage(&amp;pGrayscaleImage);   // 释放内存 
  pGrayscaleImage = NULL;

  cvWaitKey(10);   // 等待若干毫秒 
}

cvReleaseCapture(&amp;pCapture);   // 停止捕获并释放摄像头资源 
cvReleaseHist(&amp;pHist);
cvReleaseImage(&amp;pFrameB);
cvReleaseImage(&amp;pFrameSub);

pCapture = NULL;
pHist = NULL;
pFrameB = NULL;
pFrameSub = NULL;
pFrame = NULL;
pFrameA = NULL;

cvDestroyWindow(strCameraWindowName.c_str());    // 销毁窗口 
cvDestroyWindow(strDiffWindowName.c_str());
</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 />
（1）<span style="color:#b22222;">IplImage *pFrameB = cvCreateImage(cvSize(pFrame-&gt;width, pFrame-&gt;height), pFrame-&gt;depth, pFrame-&gt;nChannels);</span><br />
创建B帧图像的时候，后面的参数都是通过pFrame来获取的，如果这几个参数你随意填写，那么就会导致程序编译可通过，运行时崩溃。所以我前面先抓取了一帧，再通过这一帧来获取B帧图像的参数，这样就完全符合了。<br />
（2）cvQueryFrame函数返回的指针总是指向同一块内存&mdash;&mdash;如果你不知道这一点，并且B帧图像是通过cvQueryFrame获取的，那么可能你调试了半天，却发现A帧、B帧的内容始终相同，二者相减得到的结果永远不变，motion detection就不起作用了。所以我把B帧图像用cvCreateImage来创建，A帧用cvQueryFrame来获取，这样就没有问题了。<br />
（3）由于两帧的检测时间较短，所以可能在多个瞬间触发多次动作，为此我根据时间戳做了一些简单的处理，来防止同一秒内触发多次动作。<br />
（4）其他的代码，各位看看就明白了，也无需过多的解释。</p>
<p><span style="background-color:#afeeee;">【2】</span>发微博<br />
我选择的是腾讯微博。<br />
不得不承认，腾讯微博对C++开发者的支持不足，下载回来的开发包里，仅仅同音的错别字就有一堆（可见开发API的同学用的是拼音输入法）。另外，还有各种各样的问题，例如，API Example是无法编译的&mdash;&mdash;原因是ApiType.cpp 和 ApiType.h没有被添加进工程中，导致找不到 CApiType 类定义。再看看它的代码中，编写风格非常随意，让人看了非常难受，总之就一句话，这API你就凑合着用吧！<br />
在动手写程序发微博之前，需要先在腾讯的网页上申请成为开发者，否则你的程序是无法用微博API来发微博的。申请的过程非常简单，当然你必须先有一个QQ号，登录后，在<a href="http://open.t.qq.com/develop.php" target="_blank" rel="noopener noreferrer"><span style="color:#ff0000;">这个页面</span></a>申请。申请之后，你需要在腾讯的网页上点击创建一个<strong><span style="color:#b22222;">客户端应用</span></strong>&mdash;&mdash;尽管这个时候，你还连程序都没有开始写，但是这是先决条件，不这样做的话，你就算写好了程序也用不了，所以我就把这个过程先全部做好了，再开始写程序的事。<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 />
创建客户端应用的页面如下图所示：</p>
<div style="text-align: center; ">
	<a href="http://www.codelast.com" target="_blank" rel="noopener noreferrer"><img decoding="async" alt="create a client app" src="http://www.codelast.com/wp-content/uploads/2012/01/create_client_app.png" style="width: 581px; height: 277px; " /></a></div>
<p>点击之后只需要填写少许内容就可以创建一个客户端应用了。<br />
创建应用之后，你可以看到你所创建的应用的<span style="color:#ff0000;">App Key</span>（一串数字）和<span style="color:#ff0000;">App Secret</span>（数字和字母的混合），这两个字符串在你写程序发微博的时候会用到：</p>
<div style="text-align: center; ">
	<a href="http://www.codelast.com" target="_blank" rel="noopener noreferrer"><img decoding="async" alt="" src="http://www.codelast.com/wp-content/uploads/2012/01/app_info.png" style="width: 350px; height: 280px; " /></a></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 />
在获取了以上所需的信息后，用API发微博的过程大致可以描述为：<span style="color:#0000cd;">通过App Key和App Secret跳转到腾讯的页面去获取oauth_verifier&rarr;用户人工输入oauth_verifier&rarr;通过oauth_verifier获取Access Key和Access Secret&rarr;授权通过，可以发微博了</span>。<br />
这个过程的demo，在腾讯微博的API Example中很详细地作了演示，不过，它的编码风格非常不规范，乱就一个字，会耽误开发者的时间。<br />
正因为腾讯微博API Example已经有了例子，所以我在这里就不把发微博相关的代码全部放上来了，只是提醒大家注意以下几点：<br />
（1）你的VC++工程中，只需要引入腾讯微博API中的一个库文件：QWBlogAPI.lib。<br />
（2）你的VC++工程需要以下头文件：</p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
JsonParser.h
UtilString.h
WeiboApi.h
WeiboParam.h
XmlParser.h
weibo.h
</pre>
<p>（3）你的程序运行时，需要以下dll：</p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
curllib.dll
libeay32.dll
openldap.dll
QWBlogAPI.dll
ssleay32.dll
</pre>
<p>这些文件在腾讯微博开发包中都能找到。<br />
（4）发普通微博，option是用<span style="color:#0000ff;">TXWB_T_ADD</span>；发带图片的微博，option是用<span style="color:#0000ff;">TXWB_T_ADD_PIC</span>。图片作为参数添加到CWeiboParam对象中时，是需要特殊处理的（详见API Example）。<br />
（5）微博发不出去时，一定要检查发送内容中的&ldquo;content&rdquo;的字符串是什么编码的！别以为字符串里有内容就是对的，我在这上面折腾了不少时间，就是没注意这个问题。可以用API Example中的<span style="color:#a52a2a;">Unicode2Mbcs</span>函数来转换一个CString到合适的字符串，很管用。<br />
（6）oauth_verifier的值，是在腾讯网页的地址中获取到的，而不是在网页正文中。你跳转到类似于如下的网址后（其实就是腾讯首页）：</p>
<pre class="brush:plain;first-line:1;pad-line-numbers:true;highlight:null;collapse:false;">
http://www.qq.com/?oauth_token=XXX&oauth_verifier=XXX&openid=&openkey=
</pre>
<p>就可以肉眼识别出其值了。<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(175, 238, 238); ">【3】</span>软件UI<br />
UI很简单，但是调起来烦人。就截几幅图吧：</p>
<div style="text-align: center; ">
	<a href="http://www.codelast.com" target="_blank" rel="noopener noreferrer"><img decoding="async" alt="" src="http://www.codelast.com/wp-content/uploads/2012/01/cameragirl_ui_1.png" style="width: 438px; height: 324px; " /></a><br />
	&nbsp;</div>
<div style="text-align: center; ">
	<a href="http://www.codelast.com" target="_blank" rel="noopener noreferrer"><img decoding="async" alt="" src="http://www.codelast.com/wp-content/uploads/2012/01/cameragirl_ui_2.png" style="width: 405px; height: 313px; " /></a></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>
<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/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%e6%91%84%e5%83%8f%e5%a4%b4%e5%a8%98%e6%9d%a5%e4%ba%86/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
	</channel>
</rss>
