python OpenCV基础(一)

来源:互联网 发布:jdk 7u80 linux x64 编辑:程序博客网 时间:2024/05/17 03:35

一般的OpenCV应用程序都是在C++中编写的,在C++的接口支持方面,OpenCV也做的比较好。但笔者比较懒,厌烦了VC编程的繁锁,虽然对matlab情有独钟,怎奈matlab并不是一个编程语言,做图像处理的算法还可以,但要牵涉到文件处理、网络应用等方面就有点力不从心了。于是我将目光投向了python

     python的优缺点就不说了,总的来说,选择python的理由是因为我需要一种方便、实用、不需要考虑太多细节的语言工具,python刚好符合了我的要求。OpenCVpython的接口方面提供了两个版本:‘CV2’和‘CV’(笔者使用的OpenCV版本为2.4.2)。其中CV2CV的扩展版本。CV2是真正针对python语言编写的,而CV版则有点像C++接口与Python语言的结合体。这是因为,在CV2中,OpenCV主要借助numpy软件包做为协助进行数据处理,其数据的操作更像matlab——直观、方便,而CV版则基本保留了C++接口的繁锁形式。例如,在CV2中,我们可以像matlab一样,使用‘imread’就可以读取一幅图像,而CV中则需要使用与C++相似的函数‘LoadImage’,同时CV中的数据结构也基本遵从了C++的接口。

  由于笔者在学习OpenCV的同时也想学习一下C++的接口,所以我选择比较‘低’的CV版本,而不是CV2。结合了C++OpenCV接口与python语言的CV版有时就像一个怪胎,因为有时你即不能用C++那样进行调用,又不可以使用CV2的调用方式,这可能会给许多初学者造成困难。下面笔者将结合个人的学习实践,说一下python中应用CV的一些问题。希望可以给部分网友提供帮助。

一、工具环境:

Python环境建议使用Eclipse+PyDev,当然你需要先装python解释器,建议装python2.7版本。在Eclipse环境中使用PyDev可以充分发挥Eclipse的编辑功能,如代码提示、关键字高亮还有强大的代码调试功能。另外,建议安装好Pythonxy,因为该软件集成了很多的python软件包,省去分别下载的麻烦,同时pythonxy中自带的Opencv是编译好的动态链接库的形式,在处理大数据时数据的计算速率明显大于pydpythonOpenCV编译版本)版本。当然,如果想省事点,可以从OpenCV的官网下载最新版的OpenCV发布包,在发布包的‘build’目录下,可以找到python的编译文件cv2.pyd,将此文件拷到pythonsite-package目录下也可以顺利的使用OpenCV

二、应用CV时要注意的地方

1)、虽然CV版不同于CV2并不需要numpy包的支持,但建议在文件中也将numpy包导入进来。在某些多个数据操作的情况下,我们其实可以借助numpy的函数进行处理,使数据操作变得更方便。

2)、矩阵初始化。在C++中,直接调用cvCreateMat函数是就可以利用数组进行初始化的,但在CV中,cv.CreateMat函数并没有这个接口,cv.CreateMat只能创建一个空的矩阵。对所创建矩阵的初始化可以有以下几个方法:
a、单个元素分别赋值。这里可以使用for循环,如:

import cv2.cv as cv

init_val=[[1,2,3],[4,5,6],[7,8,9]]

mat=cv.CreateMat(3, 3, cv.CV_8UC1)

for i in range(mat.rows):

    for j in range(mat.cols):

        mat[i,j]=init_val[i][j]#逐个元素写入mat中。注意mat[i,j]是一个元组(tuple),当mat有多个通道时这里要对每个通道同时赋值,以改写改写整个元组,元组内的元素是不可写的

print np.asarray(mat[:,:])#转化为array再打印

Print函数是无法直接打印cvmat类型的,我们需要将其转换为array类型。打印结果为:

[[1 2 3]

 [4 5 6]

 [7 8 9]]

b、借助numpy赋值:

import numpy as np

import cv2.cv as cv

init_val=[[1,2,3],[4,5,6],[7,8,9]]

mat=cv.CreateMat(3, 3, cv.CV_8UC1)

# for i in range(mat.rows):

#     for j in range(mat.cols):

#         mat[i,j]=init_val[i][j]

mat_arr=np.asarray(mat[:,:])#转化为array,注意输入是mat[:,:]

mat_arr[:,:]=init_val #注意这里是对mat_arr赋值,而不是mat

print np.asarray(mat[:,:])#打印显示mat内的内容

这里的打印结果与方法a的相同。注意,调用print时仍是打印mat而不是mat_arrmat_arr可以看成是mat的指针,虽然mat_arr的数据类型为numpyarray类型,但其指向的数据地址仍在mat中,所以对mat_arr的改写就是对mat的改写。

C、多通道矩阵的赋值:

假如要改写多通道矩阵中某个元素就必须采样如下的形式:

matND=cv.CreateMat(3, 3, cv.CV_8UC3)

matND[1,1]=(1,2,3)#要赋值一个元组,列表也可以,但必须是多个通道同时赋值,也就是对整个元组改写

print matND[1,1]

而不可以这样matND[1,1][0]=3#matND[1,1]返回一个元组,不可以对元组内数据改写

D、矩阵、图像数据复制。数据复制操作均须调用专门的copyclone函数,上述mat[:,:]都得到矩阵的指针而已,如mat_arr中的数据发现改变时,mat的数据也会发生改变。

 

3)、图像数据的类型转换。

经常,我们处理的是8位整型的灰度或彩色图。但是进行处理时往往需要的是浮点型。这里可以借助cv.Scale这个函数,将图像数据转换到我们想要的类型,注意这里不是指cvmatiplimage等类型间的转换,仅是每个像素数据的存储长度的转换:

对图像做简单的DCT变换:

import cv2.cv as cv

img=cv.LoadImageM('lena.jpg')

img_gray=cv.CreateMat(img.rows, img.cols, cv.CV_8UC1)

cv.CvtColor(img, img_gray , cv.CV_BGR2GRAY)

img_dct=cv.CreateMat(img.rows,img.cols,cv.CV_32FC1)

img_gray_32f=cv.CreateMat(img.rows,img.cols,cv.CV_32FC1)

cv.Scale(img_gray, img_gray_32f)  #8位无符号型转换为浮点型

cv.DCT(img_gray_32f, img_dct,cv.CV_DXT_FORWARD)

4)、使用numpy包进行数据处理的方便性。这里以做一幅图像的反色为例:

numpy包时,我们需要对图像的每个像素都取反 :

import cv2.cv as cv

img=cv.LoadImage('lena.jpg')

img_tr=cv.CreateImage(cv.GetSize(img), img.depth, img.channels)

for i in range(img.height):

    for j in range(img.width):

        img_tr[i,j]=(255-img[i,j][0],255-img[i,j][1],255-img[i,j][2])

#对图像每个通道进行取反

利用numpy包,则只需要如下处理:

import cv2.cv as cv

import numpy as np

img=cv.LoadImage('lena.jpg')

img_tr=cv.CreateImage(cv.GetSize(img), img.depth, img.channels)

img_tr=np.asarray(cv.GetMat(img))

img_tr[:,:]=255-img_tr#图像反色

 

 

未完待续

0 0
原创粉丝点击