pycharm 2016 注册码_360知识管理

mikel阅读(1060)

pycharm 2016 注册码

来源: pycharm 2016 注册码_360知识管理

pycharm 2016 注册码(2017.2.19更新)

BIG3CLIK6F-eyJsaWNlbnNlSWQiOiJCSUczQ0xJSzZGIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiIiwiYXNzaWduZWVFbWFpbCI6IiIsImxpY2Vuc2VSZXN0cmljdGlvbiI6IkZvciBlZHVjYXRpb25hbCB1c2Ugb25seSIsImNoZWNrQ29uY3VycmVudFVzZSI6ZmFsc2UsInByb2R1Y3RzIjpbeyJjb2RlIjoiQUMiLCJwYWlkVXBUbyI6IjIwMTctMTEtMjMifSx7ImNvZGUiOiJETSIsInBhaWRVcFRvIjoiMjAxNy0xMS0yMyJ9LHsiY29kZSI6IklJIiwicGFpZFVwVG8iOiIyMDE3LTExLTIzIn0seyJjb2RlIjoiUlMwIiwicGFpZFVwVG8iOiIyMDE3LTExLTIzIn0seyJjb2RlIjoiV1MiLCJwYWlkVXBUbyI6IjIwMTctMTEtMjMifSx7ImNvZGUiOiJEUE4iLCJwYWlkVXBUbyI6IjIwMTctMTEtMjMifSx7ImNvZGUiOiJSQyIsInBhaWRVcFRvIjoiMjAxNy0xMS0yMyJ9LHsiY29kZSI6IlBTIiwicGFpZFVwVG8iOiIyMDE3LTExLTIzIn0seyJjb2RlIjoiREMiLCJwYWlkVXBUbyI6IjIwMTctMTEtMjMifSx7ImNvZGUiOiJEQiIsInBhaWRVcFRvIjoiMjAxNy0xMS0yMyJ9LHsiY29kZSI6IlJNIiwicGFpZFVwVG8iOiIyMDE3LTExLTIzIn0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMTctMTEtMjMifSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjAxNy0xMS0yMyJ9XSwiaGFzaCI6IjQ3NzU1MTcvMCIsImdyYWNlUGVyaW9kRGF5cyI6MCwiYXV0b1Byb2xvbmdhdGVkIjpmYWxzZSwiaXNBdXRvUHJvbG9uZ2F0ZWQiOmZhbHNlfQ==-iygsIMXTVeSyYkUxAqpHmymrgwN5InkOfeRhhPIPa88FO9FRuZosIBTY18tflChACznk3qferT7iMGKm7pumDTR4FbVVlK/3n1ER0eMKu2NcaXb7m10xT6kLW1Xb3LtuZEnuis5pYuEwT1zR7GskeNWdYZ0dAJpNDLFrqPyAPo5s1KLDHKpw+VfVd4uf7RMjOIzuJhAAYAG+amyivQt61I9aYiwpHQvUphvTwi0X0qL/oDJHAQbIv4Qwscyo4aYZJBKutYioZH9rgOP6Yw/sCltpoPWlJtDOcw/iEWYiCVG1pH9AWjCYXZ9AbbEBOWV71IQr5VWrsqFZ7cg7hLEJ3A==-MIIEPjCCAiagAwIBAgIBBTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTE1MTEwMjA4MjE0OFoXDTE4MTEwMTA4MjE0OFowETEPMA0GA1UEAwwGcHJvZDN5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcQkq+zdxlR2mmRYBPzGbUNdMN6OaXiXzxIWtMEkrJMO/5oUfQJbLLuMSMK0QHFmaI37WShyxZcfRCidwXjot4zmNBKnlyHodDij/78TmVqFl8nOeD5+07B8VEaIu7c3E1N+e1doC6wht4I4+IEmtsPAdoaj5WCQVQbrI8KeT8M9VcBIWX7fD0fhexfg3ZRt0xqwMcXGNp3DdJHiO0rCdU+Itv7EmtnSVq9jBG1usMSFvMowR25mju2JcPFp1+I4ZI+FqgR8gyG8oiNDyNEoAbsR3lOpI7grUYSvkB/xVy/VoklPCK2h0f0GJxFjnye8NT1PAywoyl7RmiAVRE/EKwIDAQABo4GZMIGWMAkGA1UdEwQCMAAwHQYDVR0OBBYEFGEpG9oZGcfLMGNBkY7SgHiMGgTcMEgGA1UdIwRBMD+AFKOetkhnQhI2Qb1t4Lm0oFKLl/GzoRykGjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBggkA0myxg7KDeeEwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4ICAQC9WZuYgQedSuOc5TOUSrRigMw4/+wuC5EtZBfvdl4HT/8vzMW/oUlIP4YCvA0XKyBaCJ2iX+ZCDKoPfiYXiaSiH+HxAPV6J79vvouxKrWg2XV6ShFtPLP+0gPdGq3x9R3+kJbmAm8w+FOdlWqAfJrLvpzMGNeDU14YGXiZ9bVzmIQbwrBA+c/F4tlK/DV07dsNExihqFoibnqDiVNTGombaU2dDup2gwKdL81ua8EIcGNExHe82kjF4zwfadHk3bQVvbfdAwxcDy4xBjs3L4raPLU3yenSzr/OEur1+jfOxnQSmEcMXKXgrAQ9U55gwjcOFKrgOxEdek/Sk1VfOjvS+nuM4eyEruFMfaZHzoQiuw4IqgGc45ohFH0UUyjYcuFxxDSU9lMCv8qdHKm+wnPRb0l9l5vXsCBDuhAGYD6ss+Ga+aDY6f/qXZuUCEUOH3QUNbbCUlviSz6+GiRnt1kA9N2Qachl+2yBfaqUqr8h7Z2gsx5LcIf5kYNsqJ0GavXTVyWh7PYiKX4bs354ZQLUwwa/cG++2+wNWP+HtBhVxMRNTdVhSm38AknZlD+PTAsWGu9GyLmhti2EnVwGybSD2Dxmhxk3IPCkhKAK+pl0eWYGZWG3tJ9mZ7SowcXLWDFAk0lRJnKGFMTggrWjV8GYpw5bq23VmIqqDLgkNzuoog==

Meteor与精益创业 - BitTiger.io - 知乎专栏

mikel阅读(1995)

来源: Meteor与精益创业 – BitTiger.io – 知乎专栏

作者:Mingche Su
链接:https://zhuanlan.zhihu.com/p/20139000
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

今天要和大家分享的是目前最火爆的网站开发框架之一-Meteor。它是一个搭建在Node.js之上,用于快速开发动态网站的工具。Meteor和其他开发工具相比最大的优势就是它的动态更新。这个应该怎么理解呢?举个最简单的例子,你觉得Wikipedia和Google Doc最大的区别是什么呢。在现实生活中,两个人看一篇文章,一个人做标注,另一个人马上就可以看到。如果这两个人是在Wikipedia上看同一篇文章,一个人修改了文章中的一句话,另一个人如果不刷新页面是永远都不会看到更新的(这里可以不考虑Wikipedia审批的过程)。而如果两个人都是在用Google Doc做相同的事情,任何改动都是一目了然,而且是实时的。Meteor实现的就是这种实时动态的交互方式,把现实拉近网络。
网络开发技术的演变

网络技术的更新换代是非常之快的,真的可谓是日新月异。归根结底还是源于人类的本性上对网络的依赖。人是一种社交动物,而网络正是一种可以在很大程度上增强人类社交范围和能力的工具。在正式介绍Meteor之前,我觉得有必要先给对网络开发技术不熟悉的朋友普及一下网络开发技术的演变过程,网站开发大牛可以直接跳到下一个部分。
最开始的网站开发是非常简单纯粹的,前端就是用户的电脑浏览器,后端就是网站的服务器。前端只做两件事:发出请求,等待回复。后端呢,就储存着一个网页,有人来要的时候就发给他。网络构建就是这么简单。后面随着网页的内容越来越多,越来越复杂,后端开始逐渐根据功能分散成Apache Server + PHP + SQL DB。从名字也可以看出就是把服务器和数据库分置开来。这样可以更方便管理大量的数据。但在此时前端并没有发生任何变化,用户的浏览器还是继续做着要、等、拿三件事。
再之后,就来到了网络技术产生重大变革的时刻。随着AJAX (AJAX = Async JavaScript + XML) 技术的到来,Web 2.0走进了我们的生活。在这个阶段,前端发生了巨大的改变。JavaScript, CSS等技术使前端具备了处理数据的能力,再加上XML作为前后端信息交互的平台。前端用户的浏览器开始能够处理一些用户简单的交互需求,帮助后端服务器分担压力,大大提升了网站的响应和处理速度。
继续演进,就来到了现在MVC主导的时代,这也是大部分公司现在正在使用的网站架构模式。MVC = Model + View + Controller。 Model指的也就是data,讲我们怎么存储信息,对应的技术就是MySQL DB, MangoDB。 View指的是presentation,换句话说就是展示信息,和界面相关的东西,自然对应的就是Html, CSS, JavaScript这些前端的技术;最后一个就是Controller了, 包含了所有和逻辑处理相关的部分。一开始这个设计方式可能更多地被用在服务器端。但随着Web2.0的到来,越来越多的网络开发framework像雨后春笋一样蓬勃发展,开始在前端也搭起了MVC的架构,比如AngularJS, Backbone都实现了这一点。更有甚者,直接将前端的Javascript直接渗透到后端。Node.js就是其中之一,它让只懂Javascript本来只能做前端的工程师变成了全栈同吃。再比如很多人都开始在用pure javascript的架构,最主要的一个代表就是MEAN = MongoDB + Express.js + Angular.js + Node.js
Meteor技术

Meteor和我们上面提到的framework其实并没有非常大的区别,它也是辅助工程师搭建网站的一种工具。因为它是建立在Node.js之上,所以自然而然也就继承了Node.js所有的优势。比如你只需要会Javascript就可以全栈同吃。再比如Node.js是第三方插件,工具,资料最多的开源项目。因此很多时候你可能都不需要写很多代码,只是通过调用一些插件就能实现很多很复杂的功能。

在现在的互联网行业,很多用户需求都是由移动端驱动的。中国特殊的互联网市场环境更是将移动互联网推到了风口浪尖。以至于在做好web端开发的同时还要兼顾app的开发。做产品时你对技术的需求量就会很大。在application layer你可能需要有精通iOS和Andriod的工程师,在service layer你能需要构建懂逻辑处理和api架构的工程师,在data layer,你可能需要有精通数据处理的人。Meteor完美了解决的这方面的问题。它在你写前端网页的时候,会帮你自动生成iOS和Andriod app。可以说是一石三鸟。
现在Meteor在1.0版本主要是在用blaze来生成前端页面,它使用的是templating lanuage。你只需要写简单的html片段来包装你要展示的数据和逻辑,blaze就会自动帮你拼接成一个完整的页面。Meteor作为开源的framework,自然不能亏待了同为开源的兄弟们。不久后的2.0版本,它将支持大部分最新的前端开源framework,比如Angular.js,Facebook主导的React等等。所以很多现有的前端技术和实现方式都可以直接从其他的架构搬到Meteor。在后端数据库这边,Meteor只支持MongoDB,但在不远的未来它也将会支持其他比较流行的Database, 比如SQL,REST。
接下来要谈的是Meteor最吸引人的页面动态更新特性。虽然同为pure Javascript framework,它和MEAN还是很不同的。和MEAN架构最大的不同,MEAN你还是要做很多数据的同步,数据通信,前端后端的API的设计。Meteor在一个框架里面实现了前端后端的开发同步开发。具体来讲就是数据库中的数据发生任何变化的时候,用Meteor搭建的app是不需要人为参与就能实现前端页面更新。这在任何其他的framework里面是不可能实现的,你基本都要通过API来实现前后端信息的同步。Meteor采取的解决方案是在前端也建立一个数据库,叫做miniMango。它是跑在memory里面,通过DDP自动和后端同步,保持前后端统一。这也就使UI的更新速度非常的快 (这个技术叫做reactive rendering)。当你在前端执行任何操作的时候,你只需要去修改前端这边的数据库,后端数据库更新全部交给Meteor和DDP协议去自动执行。这里另一个好处就是Latency Compensation。不管你的网络多么糟糕,页面的反应速度都像是零延迟一样,因为你和后端没有任何交互。反过来当服务器端数据库里面的数据更新的时候,它会通知所有和它相连的所有前端数据库更新数据。为了防止给前端造成造成储存压力,这个同步机制是建立在data subscription和publication之上的,前端在建立自己的数据库之前要先告诉后端它关心什么数据,以后后端就会只推送和更新那些数据。
人无完人,Meteor当然也不可能是完美的。它也有一些缺点,和它不擅长的事。

  1. 它不适合做静态页面。因为它高度强调实时,所有的内容都是Javascript动态生成的。
  2. 它不适合做独立App。全栈技术更注重整体运行效益,对用户交互体验的设计还是有所欠缺的。
  3. 它不容易继承现有架构。技术上很难将现有的网站构架直接转移到Meteor使用
  4. 它是一个全栈技术。所以你不能只在局部使用Meteor,不能说只在前端使用

Meteor和精益创业

精益创业的核心思想就是在你有一个想法之后:

1. 快速制作和发布产品;

2. 观测用户的使用过程;

3. 在收集的中发现问题,总结经验;

4. 回到原点,优化你的解决方案。

周而复始,快速迭代,不断重复这个循环,直到你能寻找到最优解。这里就要谈到一个MVP,他不是NBA里面的最有价值球员,它指的是minimal viable product,最小可用的验证版本。一开始你制作的产品不可能是面面俱到。就算你有这个能力,也不应该一开始就包罗万象,把所有的功能都上线。快速迭代的核心理念就是在初期只做最核心的功能,在不断的验证过程中完善你的产品,减少无用的功能,增加有价值的功能。你一开始设计的功能去掉一半再去掉一半可能才是你真正的核心有价值的功能。这种创业模式完全符合Meteor快速精简的特性。
正像之前说的Meteor可能不能用来只做一个独立App或者是复杂的交互网站,但是它能在最短的时间内生成一个可用的版本。量化来讲,Meteor最适合用于制作不超过15个页面的网站。举个例子,现在很多移动端的App都依附于微信做开发,因为通过微信端口的用户倒流,获取用户的成本是最低的。微信所允许的最大页面数量也不过15个。所以这已经完全可以满足MVP的需求。

用Meteor制作这么一个网站基本分4步:

1. 绘制原型图,把想法展示出来;

2. 做出UI框架, 生成Meteor template,做出基本页面;

3. 完成从页面到逻辑的转化,实现功能;

4. 优化data publication和 data subscription。

每个阶段有一个人负责,整个制作过程基本不需要2周。你可以想象在创业初期,如果使用Meteor作为网站构建技术,迭代速度是非常快的。
最后,把Meteor官方给出的7项原则分享给大家作为总结:

1. Data on the Wire. Don’t send HTML over the network. Send data and let the client decide how to render it.

2. One Language. Write both the client and the server parts of your interface in JavaScript.

3. Database Everywhere. Use the same transparent API to access your database from the client or the server.

4. Latency Compensation. On the client, use prefetching and model simulation to make it look like you have a zero-latency connection to the database.

5. Full Stack Reactivity. Make realtime the default. All layers, from database to template, should make an event-driven interface available.

6. Embrace the Ecosystem. Meteor is open source and integrates, rather than replaces, existing open source tools and frameworks. Simplicity Equals Productivity. The best way to make something seem simple is to have it actually be simple. Accomplish this through clean, classically beautiful APIs.

[python]there is a problem with widows installer package,a program run as part of setup did not finish as excepted. contact your support personel or package vendor

mikel阅读(950)

之前电脑上有python2.7.9,因tribon程序需要装了2.3.3,结果卸载2.7.9时提示there is a problem with widows installer package,a program run as part of setup did not finish as excepted. contact your support personel or package vendor. 现已强制卸载,但是再次安装python2.7.9时还是提示这个错误,请问有什么解决办法吗?系统是win7 64位

解决办法:

安装时选择for me,不是for all users ,(我也没选择安装pip),我的已经成功安装。

[人工智能]人脸检测及识别python实现系列(2)——识别出人脸 - Neo-T - 博客园

mikel阅读(1892)

来源: 人脸检测及识别python实现系列(2)——识别出人脸 – Neo-T – 博客园

从实时视频流中识别出人脸区域,从原理上看,其依然属于机器学习的领域之一,本质上与谷歌利用深度学习识别出猫没有什么区别。程序通过大量的人脸图片数据进行训练,利用数学算法建立建立可靠的人脸特征模型,如此即可识别出人脸。幸运的是,这些工作OpenCV已经帮我们做了,我们只需调用对应的API函数即可,先给出代码:

#-*- coding: utf-8 -*-

import cv2
import sys
from PIL import Image

def CatchUsbVideo(window_name, camera_idx):
cv2.namedWindow(window_name)

#视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
cap = cv2.VideoCapture(camera_idx)

#告诉OpenCV使用人脸识别分类器
classfier = cv2.CascadeClassifier(“/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt2.xml”)

#识别出人脸后要画的边框的颜色,RGB格式
color = (0, 255, 0)

while cap.isOpened():
ok, frame = cap.read() #读取一帧数据
if not ok:
break

#将当前帧转换成灰度图像
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

#人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数
faceRects = classfier.detectMultiScale(grey, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
if len(faceRects) > 0: #大于0则检测到人脸
for faceRect in faceRects: #单独框出每一张人脸
x, y, w, h = faceRect
cv2.rectangle(frame, (x – 10, y – 10), (x + w + 10, y + h + 10), color, 2)

#显示图像
cv2.imshow(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord(‘q’):
break

#释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()

if __name__ == ‘__main__’:
if len(sys.argv) != 2:
print(“Usage:%s camera_id\r\n” % (sys.argv[0]))
else:
CatchUsbVideo(“识别人脸区域”, int(sys.argv[1]))

先看一下程序输出结果:

程序正确的识别出了我的脸,加上空白行不到50行代码,还是很简单的。当然,绝大部分的工作OpenCV已经默默地替我们做了,所以我们用起来才这么简单。关于代码有几个地方需要重点交代,首先就是人脸分类器这行:

#告诉OpenCV使用人脸识别分类器
classfier = cv2.CascadeClassifier("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt2.xml")

这行代码指定OpenCV选择使用哪种分类器(注意,一定习惯分类这个说法,ML的监督学习研究的就是各种分类问题),OpenCV提供了多种分类器:

上图为我的电脑上安装的OpenCV3.2提供的所有分类器,有识别眼睛的(甚至包括左右眼),有识别身体的,有识别笑脸的,甚至还有识别猫脸的,有兴趣的可以逐个试试。关于人脸识别,OpenCV提供多个分类器选择使用,其中haarcascade_frontalface_alt_tree.xml是最严格的分类器,光线、带个帽子都有可能识别不出人脸。其它的稍微好点,default那个识别最宽松,某些情况下我家里的灯笼都会被识别成人脸;)。另外安装环境不同,分类器的安装路径也有可能不同,请在安装完OpenCV后根据分类器的实际安装路径修改代码。另外再多说一句,如果我们想构建自己的分类器,比如检测火焰(火灾报警)、汽车(确定路口汽车数量),我们依然可以使用OpenCV训练构建,详细说明参见OpenCV的官方文档。

接下来解释如下几行代码:

#人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数
faceRects = classfier.detectMultiScale(grey, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
if len(faceRects) > 0:          #大于0则检测到人脸                                   
    for faceRect in faceRects:  #单独框出每一张人脸
        x, y, w, h = faceRect        
        cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)

其中classfier.detectMultiScale()即是完成实际人脸识别工作的函数,该函数参数说明如下:

grey:要识别的图像数据(即使不转换成灰度也能识别,但是灰度图可以降低计算强度,因为检测的依据是哈尔特征,转换后每个点的RGB数据变成了一维的灰度,这样计算强度就减少很多)

scaleFactor:图像缩放比例,可以理解为同一个物体与相机距离不同,其大小亦不同,必须将其缩放到一定大小才方便识别,该参数指定每次缩放的比例

minNeighbors:对特征检测点周边多少有效点同时检测,这样可避免因选取的特征检测点太小而导致遗漏

minSize:特征检测点的最小值

 

对同一个画面有可能出现多张人脸,因此,我们需要用一个for循环将所有检测到的人脸都读取出来,然后逐个用矩形框框出来,这就是接下来的for语句的作用。Opencv会给出每张人脸在图像中的起始坐标(左上角,x、y)以及长、宽(h、w),我们据此就可以截取出人脸。其中,cv2.rectangle()完成画框的工作,在这里我有意识的外扩了10个像素以框出比人脸稍大一点的区域。cv2.rectangle()函数的最后两个参数一个用于指定矩形边框的颜色,一个用于指定矩形边框线条的粗细程度。

好了,人脸识别的事说清楚了,下一篇该讲讲如何准备训练数据了,只有训练数据足够多,我们的程序才能识别出这是谁,而不是无论青红皂白框个人脸就完事。

 

[人工智能]人脸检测及识别python实现系列(1)——配置、获取实时视频流

mikel阅读(1647)

1. 前言

今天用多半天的时间把QQ空间里的几篇年前的旧文搬到了这里,算是完成了博客搬家。QQ空间里还剩下一些记录自己数学学习路线的学习日志,属于私人性质,不再搬运了。过完春节,快马加鞭地重修完高阶偏导数后,终于感觉到疲惫了,潜意识里觉得是时候做点东西了,一是练练手,二是换换脑子,用新鲜东西刺激一下自己,好把学习效率保持下去。于是,我选择了自己最感兴趣的人脸识别,期望能够通过摄像头识别出我自己来。正好,前两天济南新闻上说济南火车站可以刷脸进站了,招行也可以刷脸取现了,感情人家都已经大规模商用了,我这儿才刚开始研究,落后啊,继续落后啊。不管它了,知识为我所有、为我所用才是最重要的。别废话了,咱言归正传吧。

说到人脸识别,简单讲就是让程序能够识别出图像的哪个部分是人脸,然后在这个基础上考虑如何应用的问题。像早已冲出国门、走向世界的美图秀秀,以及上面说的刷脸进站、刷脸取现等都是基于人脸识别技术开发出的商用软件产品,而这一切技术的背后都离不开机器学习,更直白的说是离不开数学算法。

我想做的事情是用python写一个小程序,通过读取USB摄像头的视频流识别出我自己来。事情看起来很简单,但实际做起来需要好几个程序协作才能达成目标。首先感谢一个日本程序员,是他提供了实现思路及样例代码,国内有很多Blog和公众号转发了这篇文章,度娘可以搜到,其中一个Blog的链接如下:

 碉堡了!程序员用深度学习写了个老板探测器(附源码)

度娘能搜到的都与上面相同,千篇一律。我刚开始看到这篇文章的时候很是激动一番,觉得肯定很容易实现了,但实际动手做起来才知道坑很多。作者虽然给了思路和代码,但忽略了很多关键细节,对ML刚入门的同学来说很难实现该文章描述的案例。幸运的是,菜鸟如我,虽然期间跳坑无数,死磕了近1周的时间,我还是爬出了所有的坑,达成了最初的设想,感谢那些为了我的好奇心英勇就义的脑细胞。

       这个系列博文的目标不是要取代原博文,而是作为原博文的可操作版,把原博文缺失的细节补上,手把手教会你重现实例。所以,如果你只是想快速了解整个实例,请移步上面给出的链接去看原博文,那篇博文只需花费你几分钟的时间;如果你是个行动派,那就直接参照这个系列博文操练起来,这会花费你半天到几天的时间,请自行斟酌。

2. 准备工作

1)首先需要准备一个USB摄像头,能够支持Ubuntu之类的linux操作系统;

2)PC机上安装好Ubuntu14以上64位版本(尽量双系统不要虚拟机,不然模型训练速度会慢得像蜗牛),可以安装win7/win10,但我没有试过在64位win系统上安装tensorflow,虽然tensorflow已经支持win 64位系统;

3)请确定python3已安装,我给的代码都是在python3下调试通过的,python2只是简单试过,不保证在python2下能正常运行;

4)安装Tensorflow,如果你是独显,且支持CUDA,请安装GPU版本,否则选择CPU版本,我的机器安装的是GPU版本,OS是Ubuntu16.04麒麟,安装Tensorflow的操作说明请问度娘或谷歌,又或者参考本人的另一篇博文:

Google TensorFlow for GPU安装、配置大坑

5)安装opencv2,请安装openCV3.0以上版本(该版本支持python3和python2),参考如下两个链接:

http://www.cnblogs.com/freeweb/p/5794447.html

http://blog.csdn.net/qingyuanluofeng/article/details/51558270

操作指令以第一个链接为准,给第二个的原因是它给出了OpenCV3.0的安装方法,第一个是2.14的且是支持python2的,但第一个给出的指令已经足够用了,第二个博文指令啰嗦,当遇到如何支持python3的问题时供参考用;

6)安装keras、sklearn、PIP等,它们的安装说明网上有的是,也简单,这里就不多说了;

以上准备工作关键是前5步,后面第6步可以暂时不作操作,当执行程序时如果提示某个模块无法导入,再安装该模块也可。

3. 获取并显示USB摄像头实时视频

其实,利用OpenCV获取USB摄像头的视频流并展示出来非常简单,拢共不超过30行代码:

#-*- coding: utf-8 -*-

import cv2
import sys
from PIL import Image

def CatchUsbVideo(window_name, camera_idx):
cv2.namedWindow(window_name)

#视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
cap = cv2.VideoCapture(camera_idx)

while cap.isOpened():
ok, frame = cap.read() #读取一帧数据
if not ok:
break

#显示图像并等待10毫秒按键输入,输入‘q’退出程序
cv2.imshow(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord(‘q’):
break

#释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()

if __name__ == ‘__main__’:
if len(sys.argv) != 2:
print(“Usage:%s camera_id\r\n” % (sys.argv[0]))
else:
CatchUsbVideo(“截取视频流”, int(sys.argv[1]))

根本不需要多解释,一看就能明白。接着我们再Shell控制台执行上述代码:

其中,唯一需要解释的就是camera_id,这个就是USB摄像头的索引号,一般是0,如果0不行可以试试1、2等,除非你的摄像头已经坏了,根本不能用。

本着小步快跑,一次一点小成就的原则,系列1到此结束,系列2将会继续——内容为如何利用OpenCV识别出视频中的人脸区域。

Visual Studio 2017各版本安装包离线下载、安装全解析_IT新闻_博客园

mikel阅读(1157)

来源: Visual Studio 2017各版本安装包离线下载、安装全解析_IT新闻_博客园

关于 Visual Studio 2017 各版本安装包离线下载、更新和安装的方法以及通过已下载版本减少下载量的办法。

微软最近发布了正式版 Visual Studio 2017 并公开了其下载方式,不过由于 VS2017 采用了新的模块化安装方案,所以微软官方并未提供 ISO 镜像,但是官方提供了如何进行离线下载的方案给需要进行离线安装的用户,只不过都是英文。本文将对官方指南中的一部分进行翻译(这里说一句:翻译的部分就是最基础的离线下载和安装方案,另外,即使如以前微软提供了安装镜像,也仅会包含 Visual Studio 的基本核心组件和部分官方扩展,而微软、安卓和苹果等平台的 SDK、模拟器和第三方扩展功能等会在用户选择后联网下载。而 VS2017 的离线包是包含所有可选项的)。好了,接下来将会分为四部分来叙述,分别是离线下载安装文件、离线安装 VS2017、更新离线文件包以及如何通过已下载版本来减少下载其它版本下载量的方法。

第一部分:离线下载安装文件

这里描述是包括所有版本,截图以下载 VS2017 社区版为例:

①登入 VS 官网下载页面,选择需要的版本点击下载,下载页点此进入

②下载完成后,打开下载文件所在文件夹,Windows 8.1 及以上版本用户点击资源管理器上的文件-打开命令提示符-以管理员身份打开命令提示符;Windows 7 用户可在该文件夹空白处按住 Shift 键的情况下点击鼠标右键选择“在此处打开命令窗口”。

③根据自己下载的 VS2017 版本,在打开的命令提示符窗口输入下面对应的命令并点击回车,等待程序启动即会开始下载(以下命令用于下载完整版离线包,包含全功能以及全语言包,其中红色部分为下载文件存放路径,根据自身情况用户可自行更改)

企业版:

vs_enterprise.exe –layout c:\vs2017offline

专业版:

vs_professional.exe –layout c:\vs2017offline

社区版:

vs_community.exe –layout c:\vs2017offline

如果需要下载单一语言的或其中某几种语言的离线文件,可采用以下命令:

企业版:vs_enterprise.exe –layout c:\vs2017offline –lang zh-CN

专业版:vs_professional.exe –layout c:\vs2017offline –lang zh-CN

社区版:vs_community.exe –layout c:\vs2017offline –lang zh-CN

这里提供三种语言的参数供大家选择

  • 英语(美国):en-US
  • 中文:zh-CN(简体),zh-TW(繁体)
  • 日语:ja-JP

如果需要同时下载多种语言,可以在 –lang 后面连续加上多个语言代码参数,用空格间隔开就行,比如 — lang en-US zh-CN ja-JP,那么就会同时下载英文、中文和日文语言包。

④如需更多语言包或者更多安装指令,请参考官方离线安装命令指南:点此进入

⑤等待文件下载,不要关闭文件下载窗口,等所有文件下载完成后该窗口会自动关闭,下载过程中不要断电断网,也不要关闭窗口,当然,如果断电断网或者关闭了下载窗口,没关系,输入命令重头来过,还是会继续下载的。

第二部分:离线安装

本部分以安装社区版为例,其他版本安装过程一样,只是专业版和企业版需要激活授权。

①打开刚刚存放离线文件的路径,比如 E:\vs2017offline,然后找到 certificates 文件夹并打开,依次安装该文件夹下的软件证书。双击证书并根据提示往下走就行了,实在懒得弄就一直下一步直到提示导入成功。

②运行离线根目录下的安装程序,各版本位置如下:

企业版:离线文件存储文件夹\vs_Enterprise.exe

专业版:离线文件存储文件夹\vs_Professional.exe

社区版:离线文件存储文件夹\vs_Community.exe

③安装程序运行后,选择自己需要的模块和功能,确认所需后点击安装即可。顺便吐槽一下,社区版全工作负荷、全组件以及全语言包选择后需要空间 93.85GB,所以大家还是选择自己需要的安装就行了……另外,需要 Python 扩展支持的朋友,可以自己下载 Python 安装,或者安装完成后自行到扩展添加,官方安装文件对 Python 扩展的包含据说要等下次更新……

④等待安装完成即可使用了。

第三部分:更新离线文件包

这部分比较简单,步骤如下:

①当微软提示有版本更新后,到官网下载最新的在线安装执行文件,下载地址:点此进入

②按步骤执行本文第一部分下载离线安装文件的步骤,但是必须注意,–layout 后的下载文件夹路径必须是旧版本离线文件存储的位置(如果你之前下载好没移动过那就是之前的下载路径),执行命令后安装程序会扫描已有文件并下载更新文件和新增文件。

③更新完成后可再次执行离线文件夹根目录下的安装程序进行软件更新,或者 VS 中直接检查更新,更新新版本理论上无需重新导入证书除非有新证书被下载。

第四部分:通过已下载版本减少其他版本离线下载量

这部分也很简单,原理就是社区版、专业版和企业版有大多数组件其实是相同,如果用户想离线下载所有版本,那么没有那个必要,企业版包含了其它所有版本的组件,所以理论上用户只用下载企业版即可,安装时是可选择安装社区版、专业版或者企业版的。当然目前前面所述只是理论,毕竟我没试验,当然以下方法可以百分百保证需要的用户用最少的下载量完成下载所有版本的 VS2017。

如果你已经下载好了其中一版,均可进行如下操作:

①创建两个新文件夹,根据你自己的爱好重命名,最好是英文名。

②将已经下好的版本的所有文件都分别复制到这两个新文件夹中,并删除由之前下载程序下载在根目录下的六个文件。

③下载另外两个版本的安装程序,接下来就是重复第一部分的步骤,但是命令行命令—layout 后的路径参数根据版本分别设置为你刚刚新建的那两个文件夹。

④回车执行命令,程序会扫描和检查已经下载的组件,并现在自己版本对应的缺少的以及匹配的组件,不过这部分大小不会超过 1GB,准确来说可能只有几十兆左右……

⑤等待完成,反正不一会儿就好了,然后就可以收藏三个版本的离线包了。

⑥至于更新嘛,参见第三部分。

第五部分:附加

这部分呢是附加的一部分,信息是完全下载(包含全功能全语言包)的社区版和企业版的详细文件信息,以及他们的差集文件夹信息;最大的是企业版,最小的是企业版和社区版文件夹差集的信息。最后就是,各版本离线包里面至少含以下关键字的文件夹中的内容是完全一模一样的,就是:SDK、.NET、Xamarin、Unity、Cocos、Unreal、Linux、Mac、iOS、Android、emulator……包含这些关键词的文件夹,大小合计应该超过 16GB 了……

最后嘛就是,学习编程是条非常非常痛苦和漫长的路哪,它没我们想象的那么简单,因为实际上你要学的东西并不仅仅只是编写代码……当然学习也是快乐的,每当攻破一个难题带来的成就感总会驱使你继续向更高的成就努力~~哈哈,其实我就是想说,有没有想一起自学 C# 和 .NET 的童鞋哪?

作者:寂靜·櫻花雨

3
0

css绝对定位如何在不同分辨率下的电脑正常显示定位位置? - 蓓蕾心晴 - 博客园

mikel阅读(961)

来源: css绝对定位如何在不同分辨率下的电脑正常显示定位位置? – 蓓蕾心晴 – 博客园

有时候我们在写页面中,会发现绝对定位的父级元素已经相对定位了,但是在不同分辨率的电脑下,绝对定位还是会错乱,似乎父级的相对定位并没有起了作用。

首先要明白如下几个原理:

1、笔记本电脑的分辨率一般为1366*768附近,

PC电脑的分辨率一般为 1920*1080;

以下为常见电脑分辨率:

当写网页时,如果在1920这样的大分辨率写好之后,再去小分辨率的笔记本看同样的这个网页,会发现,笔记本电脑显示的基本为宽屏大显示器下网页放大至1.5倍左右的展示效果。

2、为了页面在不同的分辨率下正常显示,要给页面一个安全宽度,一般在做1920px宽的页面时,中间要有一个1200px左右的安全宽度,并且居中,所有的内容要写在这个宽度的box里,如果有背景图或者轮播图必须通栏整个页面的时候,一定要设置成居中对齐,这样当分辨率降低之后,背景图或者Banner图左右、中间1200宽度的盒子依然居中对齐,不会出现向左向右偏离。

盒子里的div等小盒子可以用百分比来表示,来达到页面自适应。

 

绝对定位的使用:

​   绝对定位的时候,该元素的父元素一定要记得设为相对定位,这样在不同分辨率下定位才不会错乱,但是前提是这个父元素在一个安全的宽度里面,如果这个父元素本身是一个会因为分辨率降低而改变的元素,则定位一定会跟着乱。

在布局页面结构的时候,一些box框架是必不可少的,比如1200px安全宽度的div。

例如:做一个活动页面,其中这个页面背景为一个大图,在这个大图上要放一些小图来与大图实现定位,绝对不能以大图直接作为背景!

而是在放大图背景的div里继续放一个安全宽度div,再把它作为父元素做相对定位,给里面的子元素做绝对定位,这样就不会出现不同分辨率下绝对定位错乱的问题了。

 

通过总结网友经验,通过加zoom属性,可以让页面某个区块根据分辨率不同进行自动缩放到合适区域,但是有个bug,就是火狐浏览器打死都不支持这个属性,即使用transform:scale(x,y);属性也于事无补。还有一个小问题,在页面加载慢的时候重新刷新页面会先显示放大的效果,再变为缩小后的效果,会闪一下,这个还没找到解决办法,希望懂的朋友们多多交流。

zoom代码如下:

1 $(function(){        var w=window.screen.width;        var zoom=w/1920;
2         $("#container").css({
3         "zoom",zoom,
4         "-moz-transform":"scale("+zoom+")",
      "-moz-transform-origin":"top left"
5         });
6  });

 

zoom:当前屏幕分辨率宽度/1920;

zoom属性的浏览器支持性:

结果是:除了firefox以外,其他浏览器可以正常支持zoom属性,并且页面需要缩放的区块整体缩放到了适应当前分辨率的效果,而transform:scale 则是先把页面显示为已经把原本页面放大后再使用scale,则该缩小相当于当前页面下缩小的效果了,两边自然会留白。

PS:我觉得zoom属性蛮好用的,怎么现在都不怎么用了呢,居然firefox还不支持,而且很难找到解决办法。所以只能好好改变自己代码结构,提高代码的严谨性了,写出高效高兼容的代码,是每一个前端义不容辞的责任。
【注:该文章整合网友意见与经验总结所得】

有前途的程序员的16个习惯,你拥有几个?_IT新闻_博客园

mikel阅读(1031)

来源: 有前途的程序员的16个习惯,你拥有几个?_IT新闻_博客园

  慎于说 Yes

在没有搞清楚开发需求、任务工作量、团队期望值之前,有前途的程序员不会轻易答应。特别是对于新人来说,比较急于表现自己,对于同事或者老板的工作安排来者不拒,精神可嘉,方法不可取。承诺太多,会出现自己无法按时完成的情况,即使按时完成,也可能没有达到别人的期望值,长期以往别人对你的失望会越来越多。

  敢于说 No

看起来和第一条雷同,其实细究起来不一样。第二条执行起来比第一条难得多。当遇到明显不合理的要求时,可以考虑拒绝,前提是准备好了全面充分的理由。不要经常说 No,但是一旦说了,就要切中要害。有前途的程序员不会闷头干活,知道自己的定位和团队期望,分清楚哪些是不合理的要求,哪些是合理的要求,然后把明显不合理的要求和领导沟通下,取得支持。

  构建自己的知识体系

在信息爆炸的年代,碎片化的知识很多,系统学习的时间越来越少,如果没有自己的知识体系,很容易被淹没在知识的海洋中,而且难以记忆。100 分程序员推荐的做法,通过 Wiki 或者其他知识管理工具构建一个知识框架,大的分类可以包括软技能、架构、语言、前端、后端等,小的分类可以更细化。

  培养大局观

程序员比较容易陷入的困境是专注于自己的一亩三分地,不关心团队的进度和业绩,也不关心软件的整体架构和其他模块。这种状态长期下去没有好处,特别是在大公司中,逐渐成长为一颗螺丝钉。100 分程序员会在工作之余,多看看其他在做什么,看看团队的整体规划,看看软件系统的架构和说明文档。对自己的工作更理解,而且知道为什么这个产品应该这样设计,为什么领导应该这样做规划,这种大局观非常有利于自己的职业生涯。

  代码规范

程序员在新手时期需要培养良好的代码规范。最直接的办法,遵循公司已有的代码规范(如果没有类似的规定,也是醉了),从简单的变量命名到模块划分,有些规则可以导入到编码工具中,更多的部分需要自己体会和遵守。关于此方面的知识,最权威的书籍是《代码大全》,别误会,书名是个美丽的错误,里面不是代码集锦。对于新手来说,养成一个统一的编码风格非常重要,是基础一步。

代码审查

把这个单独拎出来说,是因为对于程序员来说很重要。很多快速成长的公司没有这个步骤,建议大家能够坚持下来。让别人审查自己的代码,可以得到更多的反馈,也是和同事交流的好机会;审查别人的代码,可以借鉴别人的经验和思路。通常情况下,代码审查比自己写代码的收获更大,对于新手来说更有价值。只要你想做,不论形式是不是正规,都可以执行下去,最好形成团队的习惯。

  一个时间段内只专注于一种类型的语言

如果你正在设计或开发网站,你将需要同时熟悉多种不同的语言。你可能会想同时学习所有的这些语言,特别是考虑到它们是如何相互关联的。

我想,在某种程度上,这是不可避免的。但如果你真的想快速提高,我建议你专注于一个特定领域的专业知识。你想更好地利用 CSS?把你的重点放在这一点。尝试使用一个单一的 HTML 文档只使用 CSS 实现不同的布局。 CSS Zen Garden 是一个使用相同布局实现不同页面样式非常棒的例子。你也可以通过查找元素的列表,并把精力集中在里面。举个例子来说,你熟悉 CSS2,但想提升对 CSS3 的理解,你可以学习 CSS3 属性并逐一的实现它们。你可以阅读当前的 CSS3 规范 ,还可以通过每个模块的学习来了解它在浏览器上能(或不能)做什么。

  通过注释来写逻辑

说到编码,我有坚持很多原则和想法。其中一个就是,代码中 95% 都是逻辑。另一个就是从人类语言到编程语言,逻辑并没有改变。

这也就是意味着,如果你能在代码中写出来,也就可以用英语或者其他语言写下来。

  良好的时间管理

迟到对于任何一家公司都是个头痛的问题。作为一个程序员,有时候为了完成任务常常不得不熬夜,从而导致第二天上班就迟到了。但是我们忽略了这一点,我们的工作时间至关重要,因为在这段时间里我们要和客户同步,也要与团队其他成员一齐协作。

  深入理解客户需求

仅仅了解单一用户的表面意思是远远不够的。一个伟大的程序员应该具备能把繁琐的要求理解并分解成项目的技术任务或子任务的能力,并且最后拿到的成果应精确满足客户的需求。

  在编程之前准备好全套算法

案例、伪代码和流程图统统都是非常重要的软件开发手段。一个伟大的程序员如果没有先准备好算法,那么他是不会像傻小子一样兴冲冲地开工写代码的。写代码实际上只是一个编码任务。

  理解并帮助定义验收标准

是否需要高层次测试脚本是由产品所有者决定的,但是一个伟大的程序员必须能够编写技术测试脚本,并且深刻认识到跳过这些步骤可能会带来的后果。

  绞尽脑汁还是“NO”

假如抓耳挠腮还是找不出解决办法,我们该如何是好?一个伟大的程序员应该足智多谋,能灵活应对困境。他们会去询问同事,或者是向团队领导者请教;在互联网上面搜索,然后耐下心来一遍又一遍地试验。相信山穷水尽疑无路,柳暗花明又一村,投降两个字从未出现在他们的字典上。

  编程之前准备好全套算法

亲~还记得我们老师逼我们画的流程图吗?还记得一个个案例和伪代码吗?他们都是灰常重要的软件开发手段。一个伟大的程序员如果木有事先准备好算法,那他会不会像个傻小子似的只顾写代码呢?所以,在开工之前,做好全套的算法是必须的。

  理解 and 帮助定义验收标准

是否需要高成次测试脚本是产品所有者决定的,但是,作为一个伟大的程序员必须能够编写技术测试脚本,并且也要认识到如果跳过了这一步骤可能会带来的后果。

  主动一点点

一个优秀的程序员不需要别人告诉他该做什么,他的主动性要比别人强一些,他可以自觉的关注流程,提高应用程序的灵活性以及快速的解决开发过程中出现的 Bug。

TF Boys (TensorFlow Boys ) 养成记(一):TensorFlow 基本操作 - Charles-Wan - 博客园

mikel阅读(1166)

来源: TF Boys (TensorFlow Boys ) 养成记(一):TensorFlow 基本操作 – Charles-Wan – 博客园

本资料是在Ubuntu14.0.4版本下进行,用来进行图像处理,所以只介绍关于图像处理部分的内容,并且默认TensorFlow已经配置好,如果没有配置好,请参考官方文档配置安装,推荐用pip安装。关于配置TensorFlow,官方已经说得很详细了,我这里就不啰嗦了。官方教程看这里:

如果安装了GPU版本的TensorFlow,还需要配置Cuda,关于Cuda安装看这里:

我们还需要一个Python编译器,这里我们使用Anaconda,Anaconda2对应Python2,Anaconda3对应Python3,我使用Anaconda2。Anaconda自带了一些常用的Python包,以及一些比较好用的Python编译器。

配置好TensorFlow以后,打开Anaconda的Spyder,输入以下代码检查TensorFlow是否可用。

复制代码
import tensorflow as tf
hello = tf.constant('Hello TensorFlow!')
sess = tf.Session()
print(sess.run(hello))
a = tf.constant(10)
b = tf.constant(32)
print(sess.run(a + b))
复制代码

如果遇到任何报错,请参考:

使用TensorFlow之前,要了解一下TensorFlow的基本知识:

1. 使用图(graphs)来表示计算;

2.在会话(Session)中执行图;

3.使用张量(tensors)来代表数据;

4.通过变量(variables)来维护状态;

5.使用供给(feeds)和取回(fetches)来传入或者传出数据。

关于详细的基础使用,请参考:, 太长不看的,至少看下代码以及代码的注释。

了解了这些基本用法以后,活动一下筋骨,来编个小程序测试一下我们学习的结果吧,目标是优化一个一次函数y = wx + b的权值w和偏置b,使得w和b接近给定的表达式y = 0.1*x + b,代码如下:

复制代码
import tensorflow as tf
import numpy as np
import os
os.environ['CUDA_VISIBLE_DEVICES']='0'
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction=0.2
sess = tf.InteractiveSession(config=config)

x_data = np.random.rand(100).astype("float32")
y_data = x_data * 0.1 + 0.3

W = tf.Variable(tf.random_uniform([1],-1.0,1.0))
b = tf.Variable(tf.zeros([1]))
y = W * x_data + b
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)
init = tf.initialize_all_variables()
sess.run(init)
for step in xrange(201):
    sess.run(train)
    if step % 20 ==0:
        print(step, sess.run(W), sess.run(b))
复制代码

 

代码运行结果如下:

可以看到经过200次迭代,权重w已经接近预设值0.1,b 接近预设值0.3,实际上80次的时候已经收敛到很好的结果了。

接下来,我们进行下一步的工作,用神经网络来进行MNIST手写数字的识别,MNIST手写数字分 training 和 test 两个大类,training 有6万张28*28大小的手写数字,test有1万张28*28大小的数字,更具体的介绍看这里:MNIST handwritten digit database, Yann LeCun, Corinna Cortes and Chris Burges

MNIST手写数字识别在TensorFlow的example中有自带的代码来实现,官方文档也给出了很好的解释,这两个,建议都看,加强自己对TensorFlow的理解。

至此,TensorFlow已经有了基本的入门知识,然鹅,还是不足以支撑我膨胀的野心,我是要成为加勒比海盗一样的男人,我是要成为TF Boys一样的男人(背景声音:噫~~),这种基本知识怎么能满足得了我这么优秀的头脑。

接下来,我们来看TensorFlow Mechanics 101,说实话,我也不知道这个名字是什么意思,反正是个教程,管他呢,先学会再说。这里面看起来也不难啊,就是介绍了examples/tutorials/mnist/mnist.py 和 examples/tutorials/mnist/fully_connected_feed.py两个函数,顺便说一下,用pip安装之后的TensorFlow目录一般在:/usr/local/lib/python2.7/dist-packages/tensorflow/或者是/usr/lib/python2.7/dist-packages/tensorflow/这里。细看这两个文件的代码,不是很难,如果前面的知识认真看了,这个可以直接看代码而不看官方文档,实在不明白的地方可以看官方文档的解释。

在看代码的过程中,有不明白的函数,就去Python API这里找相应的函数来看,,找不到的话,可以点右上角的搜索来搜索该函数。

 

先写到这里,明天更新TensorFlow的How To。

 

 

参考文献:

1.

TF Boys (TensorFlow Boys ) 养成记(二): TensorFlow 数据读取 - Charles-Wan - 博客园

mikel阅读(1380)

来源: TF Boys (TensorFlow Boys ) 养成记(二): TensorFlow 数据读取 – Charles-Wan – 博客园

TensorFlow 的 How-Tos,讲解了这么几点:

1. 变量:创建,初始化,保存,加载,共享;

2. TensorFlow 的可视化学习,(r0.12版本后,加入了Embedding Visualization)

3. 数据的读取;

4. 线程和队列;

5. 分布式的TensorFlow;

6. 增加新的Ops;

7. 自定义数据读取;

由于各种原因,本人只看了前5个部分,剩下的2个部分还没来得及看,时间紧任务重,所以匆匆发车了,以后如果有用到的地方,再回过头来研究。学习过程中深感官方文档的繁杂冗余极多多,特别是第三部分数据读取,又臭又长,花了我好久时间,所以我想把第三部分整理如下,方便乘客们。

TensorFlow 有三种方法读取数据:1)供给数据,用placeholder;2)从文件读取;3)用常量或者是变量来预加载数据,适用于数据规模比较小的情况。供给数据没什么好说的,前面已经见过了,不难理解,我们就简单的说一下从文件读取数据。

官方的文档里,从文件读取数据是一段很长的描述,链接层出不穷,看完这个链接还没看几个字,就出现了下一个链接。

自己花了很久才认识路,所以想把这部分总结一下,带带我的乘客们。

 

首先要知道你要读取的文件的格式,选择对应的文件读取器;

然后,定位到数据文件夹下,用

["file0", "file1"]        # or 
[("file%d" % i) for i in range(2)])    # or 
tf.train.match_filenames_once

选择要读取的文件的名字,用 tf.train.string_input_producer 函数来生成文件名队列,这个函数可以设置shuffle = Ture,来打乱队列,可以设置epoch = 5,过5遍训练数据。

最后,选择的文件读取器,读取文件名队列并解码,输入 tf.train.shuffle_batch 函数中,生成 batch 队列,传递给下一层。

 

1)假如你要读取的文件是像 CSV 那样的文本文件,用的文件读取器和解码器就是 TextLineReaderdecode_csv

2)假如你要读取的数据是像 cifar10 那样的 .bin 格式的二进制文件,就用 tf.FixedLengthRecordReadertf.decode_raw 读取固定长度的文件读取器和解码器。如下列出了我的参考代码,后面会有详细的解释,这边先大致了解一下:

复制代码
class cifar10_data(object):
    def __init__(self, filename_queue):
        self.height = 32
        self.width = 32
        self.depth = 3
        self.label_bytes = 1
        self.image_bytes = self.height * self.width * self.depth
        self.record_bytes = self.label_bytes + self.image_bytes
        self.label, self.image = self.read_cifar10(filename_queue)
        
    def read_cifar10(self, filename_queue):
        reader = tf.FixedLengthRecordReader(record_bytes = self.record_bytes)
        key, value = reader.read(filename_queue)
        record_bytes = tf.decode_raw(value, tf.uint8)
        label = tf.cast(tf.slice(record_bytes, [0], [self.label_bytes]), tf.int32)
        image_raw = tf.slice(record_bytes, [self.label_bytes], [self.image_bytes])
        image_raw = tf.reshape(image_raw, [self.depth, self.height, self.width])
        image = tf.transpose(image_raw, (1,2,0))        
        image = tf.cast(image, tf.float32)
        return label, image
        
def inputs(data_dir, batch_size, train = True, name = 'input'):

    with tf.name_scope(name):
        if train:    
            filenames = [os.path.join(data_dir,'data_batch_%d.bin' % ii) 
                        for ii in range(1,6)]
            for f in filenames:
                if not tf.gfile.Exists(f):
                    raise ValueError('Failed to find file: ' + f)
                    
            filename_queue = tf.train.string_input_producer(filenames)
            read_input = cifar10_data(filename_queue)
            images = read_input.image
            images = tf.image.per_image_whitening(images)
            labels = read_input.label
            num_preprocess_threads = 16
            image, label = tf.train.shuffle_batch(
                                    [images,labels], batch_size = batch_size, 
                                    num_threads = num_preprocess_threads, 
                                    min_after_dequeue = 20000, capacity = 20192)
        
            
            return image, tf.reshape(label, [batch_size])
            
        else:
            filenames = [os.path.join(data_dir,'test_batch.bin')]
            for f in filenames:
                if not tf.gfile.Exists(f):
                    raise ValueError('Failed to find file: ' + f)
                    
            filename_queue = tf.train.string_input_producer(filenames)
            read_input = cifar10_data(filename_queue)
            images = read_input.image
            images = tf.image.per_image_whitening(images)
            labels = read_input.label
            num_preprocess_threads = 16
            image, label = tf.train.shuffle_batch(
                                    [images,labels], batch_size = batch_size, 
                                    num_threads = num_preprocess_threads, 
                                    min_after_dequeue = 20000, capacity = 20192)
        
            
            return image, tf.reshape(label, [batch_size])
复制代码

 

3)如果你要读取的数据是图片,或者是其他类型的格式,那么可以先把数据转换成 TensorFlow 的标准支持格式 tfrecords ,它其实是一种二进制文件,通过修改 tf.train.Example 的Features,将 protocol buffer 序列化为一个字符串,再通过 tf.python_io.TFRecordWriter 将序列化的字符串写入 tfrecords,然后再用跟上面一样的方式读取tfrecords,只是读取器变成了tf.TFRecordReader,之后通过一个解析器tf.parse_single_example ,然后用解码器 tf.decode_raw 解码。

 

例如,对于生成式对抗网络GAN,我采用了这个形式进行输入,部分代码如下,后面会有详细解释,这边先大致了解一下:

复制代码
def _int64_feature(value):
    return tf.train.Feature(int64_list = tf.train.Int64List(value = [value]))
def _bytes_feature(value):
    return tf.train.Feature(bytes_list = tf.train.BytesList(value = [value]))
    

def convert_to(data_path, name):
    
    """
    Converts s dataset to tfrecords
    """
    
    rows = 64
    cols = 64
    depth = DEPTH
    for ii in range(12):
        writer = tf.python_io.TFRecordWriter(name + str(ii) + '.tfrecords')
        for img_name in os.listdir(data_path)[ii*16384 : (ii+1)*16384]:
            img_path = data_path + img_name
            img = Image.open(img_path)
            h, w = img.size[:2]
            j, k = (h - OUTPUT_SIZE) / 2, (w - OUTPUT_SIZE) / 2
            box = (j, k, j + OUTPUT_SIZE, k+ OUTPUT_SIZE)
            
            img = img.crop(box = box)
            img = img.resize((rows,cols))
            img_raw = img.tobytes()
            example = tf.train.Example(features = tf.train.Features(feature = {
                                    'height': _int64_feature(rows),
                                    'weight': _int64_feature(cols),
                                    'depth': _int64_feature(depth),
                                    'image_raw': _bytes_feature(img_raw)}))
            writer.write(example.SerializeToString())
        writer.close()


def read_and_decode(filename_queue):
    
    """
    read and decode tfrecords
    """
    
#    filename_queue = tf.train.string_input_producer([filename_queue])
    reader = tf.TFRecordReader()
    _, serialized_example = reader.read(filename_queue)
    
    features = tf.parse_single_example(serialized_example,features = {
                        'image_raw':tf.FixedLenFeature([], tf.string)})
    image = tf.decode_raw(features['image_raw'], tf.uint8)
    
    return image
复制代码

这里,我的data_path下面有16384*12张图,通过12次写入Example操作,把图片数据转化成了12个tfrecords,每个tfrecords里面有16384张图。

 

4)如果想定义自己的读取数据操作,请参考

好了,今天的车到站了,请带好随身物品准备下车,明天老司机还有一趟车,请记得准时乘坐,车不等人。

 

 

参考文献:

1.

2. 没了