核心操作

核心操作目录

源代码

  • 图片的基础操作
    • 学习读和编辑像素值,使用 image ROI和其他基础操作工作
  • 图片的加工算法
    • 在图片上执行加工算法
  • 性能测量和改进技术
    • 得到解决方式是重要的。但是获取的速度也是更重要的。学习检查你代码的速度,代码优化等等

图片的基础操作

目标

学习:

  • 访问像素值并更改他们
  • 访问图片的属性
  • 设置 感兴趣区域(Region of Interest ROI)
  • 分割和混合图片

本章几乎所有的操作都和numpy更有关系而不是opencv。想要使用opencv优化你的代码需要一个好的Numpy基础

*(单行的案例会更多的展示在python终端)

访问和改变像素值

让我们首先读取一个图片

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')

你可以访问一个像素的值通过他的行和列的数据。对于BGR的图片,返回一个BGR的一个列表。对于灰度图,只返回相应的强度。

px = img[100,100]
print(px)
>>[255 255 255]
blue=img[100,100,0]
print(blue)
>>255

同样的,你可以通过这种方法更改其值

img[100,100] = [0,0,0]
print( img[100,100] )
>>[0 0 0]

彩色图片更改为灰度图片

grayimg=cv.cvtColor(img,code=cv.COLOR_BGR2GRAY)

灰度图片的访问:

gray=grayimg[100,100]
print(gray)
>>255

注意

Numpy 是一个数学计算库用于快速的列表计算。所以简单的访问每一组和每一个像素的值 并且更改 是非常非常的缓慢的并且也不鼓励这么做

注意:

上面的方法经常用于选择数组中的一个区域,例如前五行和后三行。对于单独的像素访问,Numpy数组方法,array.item()和array.itemset()用起来更好,但是他总是返回一个标量,例如要访问所有的B,G,R的值,你需要分别调用array.item()

git checkout v2.0
code/basic_operation_image.py

更好的像素方位和编辑方法:

>>> img.item(10,10,2)
59
# modifying RED value
>>> img.itemset((10,10,2),100)
>>> img.item(10,10,2)
100
git checkout v2.1

访问图片属性

图片属性包括了行数,列和评到,图片数据的类型,像素的数量等等

img.shape可以访问图片的形状。他返回了一个元组(行,列,色彩(RGB的数量))

>>> print( img.shape )
(342, 548, 3)

注意

如果一个图片是灰度图,元组仅仅返回行和列,所以这是一个很好的办法去检测一个图片是彩色的还是灰度的

img.size可以访问总的像素数量

>>> print( img.size )
562248

img.dtype包含了图片的的数据类型

>>> print( img.dtype )
uint8

注意

img.dtype 在debug的时候非常重要的。因为一个大型数据会引发Open-CV-python代码的 无效数据类型的错误

图片ROI

有时候,你会需要中央的图片。对于图像中的眼睛检测,首先对图像进行人脸检测。当我们得到人脸时,我们只选择人脸区域,并在其中搜索眼睛,而不是搜索整个图像。它提高了准确性(因为眼睛总是盯着脸:D)和性能(因为我们在一个小区域搜索)。

ROI又一次由Numpy的检索功能获得。这里我选区了求,并且复制他到另一个图片中的区域中。


足球

分割和混和图片的频道

有时候你需要分别工作于图片的 B,G,R频道中。在这个案例中,你需要分割BGR图片到单个通道。在这个案例中,你会需要加如到这些单独的频道到BGP图片中。你可以简单的做到他 通过:


或者

>>> b = img[:,:,0]

假如你想要设置所有的红色像素为0,你不需要首先封开这个频道,Numpy的检索很快

>>> img[:,:,2] = 0

注意:

cv.split()(就时间而言)分割是一项昂贵的操作。所以只有在你需要的时候才去做。否则就使用Numpy索引。

为图片创建边界(填充)

如果你想要创建一个图片的边界,有时候类似照片框,你可以使用cv.copyMakeBorder(),但它在卷积运算、零填充等方面的应用较多。该函数具有以下参数:

  • src:输入的图片
  • top,bottom,left,right : 边框宽度以对应方向的像素数表示
  • borderType :标志,定义要添加的边框类型。它可以是以下类型:
  • value : 边界的颜色 如果边界 的类型是 cv.BORDER_CONSTANT

看如下的结果(图片通过matplotlib展示,所以红色和蓝色频道是互换的)

便捷

#图片的加工算法

目标

  • 学习图像的几种算术运算,如加法、减法、位运算等。
  • 你会学习到一下几种方法:cv.add(),cv.addWeighted() 等等

图片叠加

您可以通过OpenCV函数,cv.add()或者简单地通过numpy操作,res = img1 + img2来添加两个图像。这两个图像应该具有相同的深度和类型,否则第二个图像只能是标量值。

注意

OpenCV添加和Numpy添加是有区别的。OpenCV加法是饱和运算,Numpy加法是模运算。

例如,思考一下的例子:

>>> x = np.uint8([250])
>>> y = np.uint8([10])
>>> print( cv.add(x,y) ) # 250+10 = 260 => 255
[[255]]
>>> print( x+y )          # 250+10 = 260 % 256 = 4
[4]

当您添加两个图像时,它将更加可见。OpenCV函数将提供更好的结果。所以最好还是用OpenCV函数。

图片融合

这也是图像的添加,但不同的权重赋予图像,使其给人一种混合或透明的感觉。图像按下式添加:

1544604303028

通过改变从0→α1中,您可以执行一个很酷的一个图像之间的过渡到另一个地方。

这里我拍了两张照片把它们混合在一起。第一幅图像的权值为0.7,第二幅图像的权值为0.3。cv.addWeighted()对图像应用以下方程。

1544604313244

γ是视为零。

img1 = cv.imread('ml.png')
img2 = cv.imread('opencv-logo.png')
dst = cv.addWeighted(img1,0.7,img2,0.3,0)
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows(

查看一下结果

tupian

按位操作

这包括位和、或、非和XOR操作。它们在提取图像的任何部分(我们将在下一章中看到)、定义和处理非矩形ROI等方面非常有用。

我想把OpenCV的logo放在图片上面。如果我添加两个图像,它会改变颜色。如果我混合它,我得到一个透明的效果。但我希望它是不透明的。如果它是一个矩形区域,我可以像上一章那样使用ROI。但是OpenCV的logo不是一个矩形。所以你可以按位操作如下:

# Load two images
img1 = cv.imread('messi5.jpg')
img2 = cv.imread('opencv-logo-white.png')
# I want to put logo on top-left corner, So I create a ROI
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols ]
# Now create a mask of logo and create its inverse mask also
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
mask_inv = cv.bitwise_not(mask)
# Now black-out the area of logo in ROI
img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)
# Take only region of logo from logo image.
img2_fg = cv.bitwise_and(img2,img2,mask = mask)
# Put logo in ROI and modify the main image
dst = cv.add(img1_bg,img2_fg)
img1[0:rows, 0:cols ] = dst
cv.imshow('res',img1)
cv.waitKey(0)
cv.destroyAllWindows()

请看下面的结果。左边的图像显示了我们创建的掩码。右图显示了最终结果。为了更好地理解,请显示上述代码中的所有中间图像,特别是img1_bg和img2_fg。

wer

代码解读:

# Load two images
img1 = cv.imread('messi5.jpg')
img2 = cv.imread('opencv-logo-white.png')

##抓出需要进行覆盖的图像
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols ]
# 创建一张灰度图
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
### 从灰度图获取一张2值图,调整阈值 (参数中的10)到可以看到整个logo。返回的ret是阈值,mask是最终的二值图
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
###  反向选取LOGO以外的像素点 
mask_inv = cv.bitwise_not(mask)

### 在roi中将logo将要移动的地方 全部置为黑色,清空
img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)
### 将logo中不需要的地方 剪掉
img2_fg = cv.bitwise_and(img2,img2,mask = mask)
### 将两种图合并
dst = cv.add(img1_bg,img2_fg)
### 代替原图
img1[0:rows, 0:cols ] = dst
cv.imshow('res',img1)
cv.waitKey(0)
cv.destroyAllWindows()

练习

  1. 在文件夹中创建图像幻灯片,使用cv在图像之间进行平滑转换。addWeighted函数

性能测量和改进技术

目标

在图像处理中,由于每秒要处理大量操作,因此必须确保代码不仅提供正确的解决方案,而且以最快的方式提供解决方案。所以在这一章,你会学到

  • 衡量代码的性能
  • 一些优化你代码性能的技巧
  • 你会看到这些方法:cv.getTickCount(),cv.getTickFrequency()

除了OpenCV, Python还提供了一个模块time,它有助于测量执行时间。另一个模块配置profile有助于获得关于代码的详细报告,比如代码中的每个函数花费了多少时间、调用了多少次等等。但是,如果您使用IPython,那么所有这些特性都是以用户友好的方式集成的。我们将看到一些重要的链接,有关更多细节,请参阅附加参考资料部分中的链接。

衡量OpenCV的性能

cv,getTickCount 函数返回引用事件(如机器切换到开启的时间)到调用该函数时的时钟周期数。因此,如果在函数执行前后调用它,就会得到用于执行函数的时钟周期数。

cv.getTickFrequency 函数返回时钟周期的频率,或每秒时钟周期的数量。因此,要计算以秒为单位的执行时间,可以执行以下操作:

e1 = cv.getTickCount()
# your code execution
e2 = cv.getTickCount()
time = (e2 - e1)/ cv.getTickFrequency()

我们将用以下示例进行演示。下面的示例应用中值过滤,其内核大小从5到49不等。(不要担心结果会是什么样子,那不是我们的目标):

img1 = cv.imread('messi5.jpg')
e1 = cv.getTickCount()
for i in xrange(5,49,2):
    img1 = cv.medianBlur(img1,i)
e2 = cv.getTickCount()
t = (e2 - e1)/cv.getTickFrequency()
print( t )
# Result I got is 0.521107655 seconds

注意

time模块也可以这样做。,使用time.time()函数,取代cv.getTickCount,然后取两倍的差。

##OpenCV中的默认优化

OpenCV的许多函数都是使用SSE2、AVX等优化的,它也包含未优化的代码。因此,如果我们的系统支持这些特性,我们应该利用它们(几乎所有现代处理器都支持它们)。它在编译时默认启用。所以OpenCV在启用的情况下会运行优化的代码,否则会运行未优化的代码。您可以使用cv. useoptimization()来检查是否启用/禁用它,使用cv. setuseoptimization()来启用/禁用它。让我们看一个简单的例子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值