资讯专栏INFORMATION COLUMN

Erlang/Elixir: 使用 OpenCV, Python 搭建图片缩略图服务器

468122151 / 2056人阅读

摘要:这篇文章是在上测试和运行的的下的安装和配置请移步到这里应用程序进程树默认启动时初始化个用于处理图片的工作进程首先安装需要的工具包使用的版本而不是系统自带的创建项目模块图像处理获取宽高把原始的二进制图片数据转换为把转换为的图

</>复制代码

  1. 这篇文章是在OSX上测试和运行的的, Ubuntu下的安装和配置请移步到这里

应用程序进程树, 默认启动 Poolboy 时, 初始化10个用于处理图片的 Python 工作进程(Worker)

首先安装OpenCV需要的工具包

</>复制代码

  1. ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  2. brew install python
  3. brew tap homebrew/science
  4. brew install opencv
  5. sudo pip install numpy
  6. sudo pip install matplotlib

使用 Homebrew 的 Python 版本, 而不是 Mac OS X 系统自带的 Python

</>复制代码

  1. alias python="/usr/local/bin/python"
创建 Elixir 项目

</>复制代码

  1. ➜ mix new opencv_thumbnail_server --sup
  2. * creating README.md
  3. * creating .gitignore
  4. * creating mix.exs
  5. * creating config
  6. * creating config/config.exs
  7. * creating lib
  8. * creating lib/opencv_thumbnail_server.ex
  9. * creating test
  10. * creating test/test_helper.exs
  11. * creating test/opencv_thumbnail_server_test.exs
  12. Your Mix project was created successfully.
  13. You can use "mix" to compile it, test it, and more:
  14. cd opencv_thumbnail_server
  15. mix test
  16. Run "mix help" for more commands.

Elixir 模块

</>复制代码

  1. require Logger
  2. defmodule OpencvThumbnailServer do
  3. use Application
  4. def start(_type, _args) do
  5. Logger.info "Start opencv thumbnail server"
  6. OpencvThumbnailServer.Supervisor.start_link()
  7. end
  8. end

</>复制代码

  1. defmodule OpencvThumbnailServer.Supervisor do
  2. use Supervisor
  3. @config Application.get_env :opencv_thumbnail_server, :settings
  4. def start_link() do
  5. Supervisor.start_link(__MODULE__, [], name: {:global,__MODULE__})
  6. end
  7. def init([]) do
  8. pool_options = @config[:poolboy]
  9. {_, name} = pool_options[:name]
  10. children = [
  11. :poolboy.child_spec(name, pool_options, @config[:module_name])
  12. ]
  13. supervise(children, strategy: :one_for_all, max_restarts: 1000, max_seconds: 3600)
  14. end
  15. end

</>复制代码

  1. defmodule OpencvThumbnailServer.Worker do
  2. use GenServer
  3. @config Application.get_env(:opencv_thumbnail_server, :settings)
  4. def start_link(python_module) do
  5. GenServer.start_link(__MODULE__, python_module, [])
  6. end
  7. def call_python(worker, function, args) do
  8. GenServer.call(worker, {:call_python, function, args}, 10_000)
  9. end
  10. def init(python_module) do
  11. IO.puts "Start worker"
  12. {:ok, pid} = :python.start_link([
  13. {:python_path, @config[:python_path]},
  14. {:python, @config[:python]}
  15. ])
  16. state = {python_module, pid}
  17. {:ok, state}
  18. end
  19. def handle_call({:call_python, function, args}, _from, state) do
  20. {module, pid} = state
  21. result = :python.call(pid, module, function, args)
  22. reply = {:ok, result}
  23. {:reply, reply, state}
  24. end
  25. def handle_call(_request, _from, state) do
  26. {:stop, :error, :bad_call, state}
  27. end
  28. def handle_info(_msg, {module,py_pid}) do
  29. {:stop, :error, {module,py_pid}}
  30. end
  31. def terminate(_reason, {_, py_pid}) do
  32. :python.stop(py_pid)
  33. :ok
  34. end
  35. end
图像处理

获取宽高

</>复制代码

  1. # -*- coding: utf-8 -*-
  2. import urllib2 as urllib
  3. import numpy as np
  4. import cv2
  5. def load_image_url(url):
  6. resp = urllib.urlopen(url)
  7. buf = resp.read()
  8. return buf
  9. def load_image_file(filename):
  10. image = cv2.imdecode(filename, cv2.IMREAD_COLOR)
  11. return image
  12. def get_photo_sizes():
  13. return [
  14. [160, 160],
  15. [320, 320],
  16. [640, 640],
  17. [1060, 1060],
  18. [1280, 1280]
  19. ]
  20. def show(buf):
  21. # print buf
  22. # x = cv2.imdecode(image, cv2.IMREAD_COLOR)
  23. # d = cv2.cvtColor(c, cv2.COLOR_RGB2BGR)
  24. np_ndarray = np.fromstring(buf, dtype=np.uint8)
  25. x = cv2.imdecode(np_ndarray, cv2.IMREAD_UNCHANGED)
  26. return cv2.imshow("NBA Image", x)
  27. def write(buf):
  28. nparray = np.fromstring(buf, dtype=np.uint8)
  29. img = cv2.imdecode(nparray, cv2.IMREAD_UNCHANGED)
  30. return cv2.imwrite("/tmp/imwrite.png", img)
  31. # def get_dimension():
  32. # url = "http://img1.gtimg.com/16/1601/160106/16010642_1200x1000_0.jpg"
  33. # resp = urllib.urlopen(url)
  34. # buf = resp.read()
  35. # x = np.fromstring(buf, dtype=np.uint8)
  36. # img = cv2.imdecode(x, cv2.IMREAD_UNCHANGED)
  37. # # height = np.size(img, 0)
  38. # # width = np.size(img, 1)
  39. # height, width = image.shape[:2]
  40. # return (width, height)
  41. def get_dimension(buffer):
  42. # 把原始的二进制图片数据转换为NpArray
  43. nparray = np.fromstring(buffer, dtype=np.uint8)
  44. # 把 nparray 转换为 opencv 的图像格式
  45. image = cv2.imdecode(nparray, cv2.IMREAD_UNCHANGED)
  46. height, width = image.shape[:2]
  47. return (width, height)
  48. def convert_color():
  49. url = "http://ww3.sinaimg.cn/mw690/6941baebgw1epzcuv9vmxj20me0hy0u1.jpg"
  50. resp = urllib.urlopen(url)
  51. buf = resp.read()
  52. x = np.fromstring(buf, dtype=np.uint8)
  53. img = cv2.imdecode(x, cv2.IMREAD_UNCHANGED)
  54. if __name__ == "__main__":
  55. get_dimension()
在 Erlang 和 Python 之间传输二进制数据

Erlang 的binary()数据类型和 Python 之间的映射关系, 在Python 2.x 中二进制数据类型为 str() 表示, Python 3.x 中为 bytes()

buf = resp.read(), 其中变量 buf 的类型为

在 Elixir 我们看到变量 buf 的值为:

</>复制代码

  1. {:ok, <<255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 1, 0, 72,
  2. 0, 72, 0, 0, 255, 219, 0, 67, 0, 8, 6, 6, 7, 6, 5, 8, 7, 7, 7,
  3. 9, 9, 8, 10, 12, 20, 13, 12, 11, 11, 12, 25, 18, 19, ...>>}
调用 Python 函数

</>复制代码

  1. {:ok, data} = OpencvThumbnailServer.Api.load_image_url("https://segmentfault.com/img/bVwhAW")
  2. OpencvThumbnailServer.Api.get_dimension(data)
  3. {:ok, {800, 431}}

创建 Python 模块

之前的 Python 图像处理模块可以组织到一个项目中多带带维护. 这里使用工具 cookiecutter 创建 Python 一个基本的项目骨架, 用于实现缩略图的功能

cookiecutter 可以通过多种方式安装, 包括pip, easy_install, conda, brew

</>复制代码

  1. pip install cookiecutter
  2. easy_install cookiecutter
  3. conda install -c https://conda.binstar.org/pydanny cookiecutter
  4. brew install cookiecutter(Mac OS X)

目录结构

</>复制代码

  1. opencv_thumbnail git:(master) tree
  2. .
  3. ├── AUTHORS.rst
  4. ├── CONTRIBUTING.rst
  5. ├── HISTORY.rst
  6. ├── LICENSE
  7. ├── MANIFEST.in
  8. ├── Makefile
  9. ├── README.rst
  10. ├── build
  11. │   ├── bdist.macosx-10.11-x86_64
  12. │   └── lib
  13. │   └── opencv_thumbnail
  14. │   ├── __init__.py
  15. │   └── opencv_thumbnail.py
  16. ├── dist
  17. │   └── opencv_thumbnail-0.1.0-py2.7.egg
  18. ├── docs
  19. │   ├── Makefile
  20. │   ├── authors.rst
  21. │   ├── conf.py
  22. │   ├── contributing.rst
  23. │   ├── history.rst
  24. │   ├── index.rst
  25. │   ├── installation.rst
  26. │   ├── make.bat
  27. │   ├── readme.rst
  28. │   └── usage.rst
  29. ├── opencv_thumbnail
  30. │   ├── __init__.py
  31. │   ├── __init__.pyc
  32. │   ├── opencv_thumbnail.py
  33. │   └── opencv_thumbnail.pyc
  34. ├── opencv_thumbnail.egg-info
  35. │   ├── PKG-INFO
  36. │   ├── SOURCES.txt
  37. │   ├── dependency_links.txt
  38. │   ├── not-zip-safe
  39. │   └── top_level.txt
  40. ├── requirements_dev.txt
  41. ├── setup.cfg
  42. ├── setup.py
  43. ├── tests
  44. │   ├── __init__.py
  45. │   └── test_opencv_thumbnail.py
  46. ├── tox.ini
  47. └── travis_pypi_setup.py
  48. 9 directories, 36 files
API实现

调用需要从 Poolboy 池中取出一个工作进程, 并调用工作进程的call_python, 进程使用完成后返还给 Poolboy 进程池, 这里对调用过程封装一下, 以简化使用.

</>复制代码

  1. defmodule OpencvThumbnailServer.Api do
  2. alias OpencvThumbnailServer.Worker
  3. def get_dimension(data) do
  4. worker = :poolboy.checkout(:opencv_thumbnail_server_pool)
  5. {w, h} = Worker.call_python(worker, :get_dimension, [data])
  6. :poolboy.checkin(:opencv_thumbnail_server_pool, worker)
  7. {w, h}
  8. end
  9. def load_image_url(url) do
  10. worker = :poolboy.checkout(:opencv_thumbnail_server_pool)
  11. image_bin = Worker.call_python(worker, :load_image_url, [url])
  12. :poolboy.checkin(:opencv_thumbnail_server_pool, worker)
  13. image_bin
  14. end
  15. end
源码

https://github.com/developerworks/opencv_thumbnail_server

参考资料

利用Python和OpenCV将URL直接转换成OpenCV格式
How to read raw png from an array in python opencv?
Install OpenCV for Python on Mac OS X
Installing scikit-image
How can i read an image from an internet url in python cv2 , scikit image and mahotas
Using Elixir, erlport with Python 2.7.9, receiving an arity error
How to read image from in memory buffer (StringIO) or from url with opencv python library
Python OpenCV convert image to byte string?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37987.html

相关文章

  • MacOS 安装 PHP的Tclip扩展实现更好的缩略

    摘要:图片中有人脸,将自动视为人脸区域为重要区域,将不会被裁剪掉。自动识别其它重要区域。如果图片中未识别出人脸,则会根据特征分布计算出重区域。源码地址安装根据上的说明,在上安装没有问题,但在我的上就挂了。首先遇到的问题就是,安装不过去。 Tclip 用于图片裁剪,有以下特点: 能进行人脸识别。图片中有人脸,将自动视为人脸区域为重要区域,将不会被裁剪掉。 自动识别其它重要区域。如果图片中...

    SwordFly 评论0 收藏0
  • 利用python进行识别相似(一)

    摘要:图像指纹与汉明距离在介绍下面其他判别相似度的方法前,先补充一些概念。汉明距离为,即代表两张图片完全一样。下一次将讲述利用和以训练好的模型来进行人脸识别。本文参考文章和图片来源的文章赖勇浩的文章下一篇地址利用进行识别相似图片二 文章简介 在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系。当然了,图像识别这个...

    HitenDev 评论0 收藏0

发表评论

0条评论

468122151

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<