OpenCV-Python教程导读-3 图像基础操作

#主要内容

  • Access pixel values and modify them
  • Access image properties
  • Setting Region of Image (ROI)
  • Splitting and Merging images

#获取和修改各像素值

##Accessing and Modifying pixel values

You can access a pixel value by its row and column coordinates. For BGR image, it returns an array of Blue, Green, Red values. For grayscale image, just corresponding intensity is returned.

1
2
3
4
5
6
7
8
9
10
px = img[10,10]
print px
# accessing only blue pixel
blue = img[10,10,0]
print blue
# modify
img[10,10]=[255,255,255]
print img[10,10]

警告 Numpy is a optimized library for fast array calculations. So simply accessing each and every pixel values and modifying it will be very slow and it is discouraged.

##更快的方法

Above mentioned method is normally used for selecting a region of array, say first 5 rows and last 3 columns like that. For individual pixel access, Numpy array methods, array.item() and array.itemset() is considered to be better. But it always returns a scalar. So if you want to access all B,G,R values, you need to call array.item() separately for all.

1
2
3
4
5
6
7
8
# accessing RED value
>>> img.item(10,10,2)
59
# modifying RED value
>>> img.itemset((10,10,2),100)
>>> img.item(10,10,2)
100

##OpenCV的坐标问题
原点在左上角
向右为X正方向,向下为Y正方向

另外要注意,在numpy设定图片大小时x,y是互换的。
比如img.shape是(600,800,3)
那么X方向有800像素,Y方向有600像素

即是在numpy的ndarray中
坐标方式是 [Y,X,CHANNEL]

#获取图像属性

##Accessing Image Properties
Image properties include number of rows, columns and channels, type of image data, number of pixels etc.

Shape of image is accessed by img.shape. It returns a tuple of number of rows, columns and channels (if image is color):

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

number of pixels is accessed by img.size

1
2
>>> print img.size
562248

size的计算方法

size = rows columns channels

Image datatype is obtained by img.dtype:

1
2
>>> print img.dtype
uint8

#ROI操作

##image ROI
ROI(region of interest)

ROI is again obtained using Numpy indexing.

1
2
>>> ball = img[280:340, 330:390]
>>> img[273:333, 100:160] = ball

#分割与合并图像通道

##Splitting and Merging Image Channels

1
2
>>> b,g,r = cv2.split(img)
>>> img = cv2.merge((b,g,r))

警告 cv2.split() is a costly operation (in terms of time), so only use it if necessary. Numpy indexing is much more efficient and should be used if possible.

#为图像添加边缘

##Making Borders for Images (Padding)
填充边缘的一些方式

If you want to create a border around the image, something like a photo frame, you can use cv2.copyMakeBorder() function. But it has more applications for convolution operation, zero padding etc. This function takes following arguments:

This function takes following arguments:

  1. src - input image
  2. top, bottom, left, right - border width in number of pixels in corresponding directions
  3. borderType - Flag defining what kind of border to be added. It can be following types:
  • cv2.BORDER_CONSTANT - Adds a constant colored border. The value should be given as next argument.
  • cv2.BORDER_REFLECT - Border will be mirror reflection of the border elements, like this : fedcba|abcdefgh|hgfedcb
  • cv2.BORDER_REFLECT_101 or cv2.BORDER_DEFAULT - Same as above, but with a slight change, like this : gfedcb|abcdefgh|gfedcba
  • cv2.BORDER_REPLICATE - Last element is replicated throughout, like this: aaaaaa|abcdefgh|hhhhhhh
  • cv2.BORDER_WRAP - Can’t explain, it will look like this : cdefgh|abcdefgh|abcdefg
  1. value - Color of border if border type is cv2.BORDER_CONSTANT

demo code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('lena.jpg',1)
px = img[10,10]
print px
# accessing only blue pixel
blue = img[10,10,0]
print blue
#modify
img[10,10]=[255,255,255]
print img[10,10]
RED = [255,0,0]
img1 = img[:,:,::-1]
replicate = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_WRAP)
constant= cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_CONSTANT,value=RED)
plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.xticks([]), plt.yticks([])
plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE')
plt.xticks([]), plt.yticks([])
plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT')
plt.xticks([]), plt.yticks([])
plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101')
plt.xticks([]), plt.yticks([])
plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP')
plt.xticks([]), plt.yticks([])
plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.xticks([]), plt.yticks([])
plt.show()

结果
Alt text

关于什么是zero-padding

Alt text

#参考资料
[1] OpenCV-Python Tutorial:Basic Operations on Images
[2] zero-padding 边缘填充