0


CV基础教程:图像上的几何变换

作者:Akula Hemanth Kumar
deephub翻译组:孟翔杰

**
**

目录

1.缩放

2.平移

3.旋转

4.仿射变换

5.透视变换

缩放

  • 图像缩放是指调整图像的大小

  • magnification称为放大

  • downsizing称为缩小

  • 理想目标-图片无损转换

  • 图像分辨率-高度(以像素为单位)*宽度(以像素为单位)

使用 numpy 模块调整图像大小

import numpy as npimport cv2from matplotlib import pyplot as pltimg = cv2.imread("imgs/chapter4/tessellate.jpg", -1)print("Input image shape - {}".format(img.shape))plt.imshow(img[:,:,::-1])plt.show()

输出

Input image shape - (240, 320, 3)

缩小图像宽度

height, width, channels = img.shape
# create blank image of half the widthresized_img_width = np.zeros((height, width//2, channels), dtype=np.int32)for r in range(height):forcin range(width//2):        resized_img_width[r][c] += (img[r][2*c])print("Width resized image shape - {}".format(resized_img_width.shape))plt.imshow(resized_img_width[:,:,::-1])plt.show()

输出

Width resized image shape - (240, 160, 3)

将图像的高度和宽度均缩小到原来的一半

resized_img = np.zeros((height//2, width//2, channels), dtype=np.int32)for r in range(height//2):forcin range(width//2):        resized_img[r][c] += (resized_img_width[r*2][c])print("Complete resized image shape - {}".format(resized_img.shape))plt.imshow(resized_img[:,:,::-1])plt.show()

输出

Complete resized image shape - (120, 160, 3)

放大图像高度

half_upsclaled_img = np.zeros((height, width//2, channels), dtype=np.int32)half_upsclaled_img[0:height:2, :, :] = resized_img[:, :, :]half_upsclaled_img[1:height:2, :, :] = resized_img[:, :, :]print("Height upscaled image shape - {}".format(half_upsclaled_img.shape))plt.imshow(half_upsclaled_img[:,:,::-1])plt.show()

输出

Height upscaled image shape - (240, 160, 3)

放大图像宽度

upsclaled_img = np.zeros((height, width, channels), dtype=np.int32)# Expand rows by replicating every consecutive rowupsclaled_img[:, 0:width:2, :] = half_upsclaled_img[:, :, :]upsclaled_img[:, 1:width:2, :] = half_upsclaled_img[:, :, :]print("Fully upscaled image shape - {}".format(upsclaled_img.shape))upscaled_img_manual = upsclaled_imgplt.imshow(upsclaled_img[:,:,::-1])plt.show()

输出

Fully upscaled image shape - (240, 320, 3)

比较原始版本和更改后的版本

f = plt.figure(figsize=(15,15))f.add_subplot(1, 2, 1).set_title('Original Image')plt.imshow(img[:, :, ::-1])f.add_subplot(1, 2, 2).set_title('Upscaled image post downscaling')plt.imshow(upsclaled_img[:, :, ::-1])plt.show()

注意:用这种方式调整图像大小会损失很多信息

使用OpenCV模块调整图像大小

  • 通过使用cv2.resize()缩小图像
  • 通过使用cv2.resize()放大图像

将图像的高度和宽度均缩小到原来的一半

import numpy as npimport cv2from matplotlib import pyplot as pltimg = cv2.imread("imgs/chapter4/tessellate.jpg", -1)height, width, channels = img.shape
# create blank image of half the widthresized_img = cv2.resize(img, (width//2, height//2))print("Downscaled image shape - {}".format(resized_img.shape))plt.imshow(resized_img[:,:,::-1])plt.show()

将操作后的图像放大至其原本的高度和宽度

height, width, channels = img.shape
# create blank image of half the widthupscaled_img = cv2.resize(resized_img, (width, height));print("Upscaled image shape - {}".format(upscaled_img.shape))upscaled_img_opencv = upscaled_imgplt.imshow(upscaled_img[:,:,::-1])plt.show()

输出

Upscaled image shape - (240, 320, 3)

比较原始图片,手动缩放的图片和使用opencv缩放的图片

f = plt.figure(figsize=(15,15))f.add_subplot(3, 1, 1).set_title('Original Image');plt.imshow(img[:, :, ::-1])f.add_subplot(3, 1, 2).set_title('Manually Upscaled post downscaling');plt.imshow(upscaled_img_manual[:, :, ::-1])f.add_subplot(3, 1, 3).set_title('Upscaled using opencv post downscaling');plt.imshow(upscaled_img[:, :, ::-1])plt.show()

使用Pillow模块调整图像大小

将图像的高度和宽度均缩小到原来的一半```

import numpy as npfrom PIL import Imagefrom matplotlib import pyplot as pltimg_p = Image.open("imgs/chapter4/tessellate.jpg")width, height = img_p.size
# create blank image of half the widthresized_img = img_p.resize((width//2, height//2))print("Downscaled image shape - {}".format(resized_img.size))plt.imshow(resized_img);plt.show()

输出

Downscaled image shape - (160, 120)

将操作后的图像放大至其原本的高度和宽度

width, height = img_p.size
# create blank image of half the widthupscaled_img = resized_img.resize((width, height))print("Upscaled image shape - {}".format(upscaled_img.size))plt.imshow(resized_img)plt.show()

输出

Upscaled image shape - (320, 240)

比较原始图片,手动缩放的图片,使用OpenCV缩放的图片和使用Pillow缩放的图片

f = plt.figure(figsize=(15,15))f.add_subplot(2, 2, 1).set_title('Original Image')plt.imshow(img[:, :, ::-1])f.add_subplot(2, 2, 2).set_title('Manually Upscaled post downscaling')plt.imshow(upscaled_img_manual[:, :, ::-1])f.add_subplot(2, 2, 3).set_title('Upscaled using opencv post downscaling')plt.imshow(upscaled_img_opencv[:, :, ::-1])f.add_subplot(2, 2, 4).set_title('Upscaled using PIL post downscaling')plt.imshow(upscaled_img)plt.show()

图片缩放的算法

什么是插值

  • 插值是一种在一组已知的离散数据点范围内构造新数据点的方法。
  • 也就是说,已知自变量的中间值估算该函数的值。
  • 也称为曲线拟合或近似值。

使用OpenCV进行插值

最近邻插值

  • 分配最接近当前像素的值。
  • 这种方法是最基础的一种方法
  • 在所有插值算法中,它的处理时间最短,因为它仅考虑一个像素-最接近插值点的像素。

双线性插值

  • 双线性插值法考虑了未知像素值周围的已知像素值的2 * 2邻域。
  • 然后,对这4个像素进行加权平均,以得出其最终插值。

双三次插值

LancZos插值

  • 高阶插值。
  • 因为在高阶中操作所以难以可视化。
  • 是一种更高维度的过滤和特征提取方法。

应该用哪种插值方法呢?

  • 默认情况下使用cv2.INTER_LINEAR。
  • cv2.INTER_AREA用于缩小。
  • cv2.INTER_CUBIC也是用于缩小,效果更好但速度较慢。
  • cv.INTER_LINEAR用于图片缩放缩放。
  • 当不考虑计算速度时可以运用其他方法。

OpenCV的算法

import numpy as npimport cv2from matplotlib import pyplot as pltimg = cv2.imread("imgs/chapter4/tessellate.jpg", -1)h, w, c = img.shape
# Downscaling and upscaling using nearest neighbor interpolationimg_n = cv2.resize(img, (w//2, h//2), interpolation = cv2.INTER_NEAREST)img_n = cv2.resize(img_n, (w, h), interpolation = cv2.INTER_NEAREST)
# Downscaling and upscaling using Bilinear interpolationimg_b = cv2.resize(img, (w//2, h//2), interpolation = cv2.INTER_LINEAR)img_b = cv2.resize(img_b, (w, h), interpolation = cv2.INTER_LINEAR)
# Downscaling and upscaling using matrix area interpolationimg_a = cv2.resize(img, (w//2, h//2), interpolation = cv2.INTER_AREA)img_a = cv2.resize(img_a, (w, h), interpolation = cv2.INTER_AREA)
# Downscaling and upscaling using cubic interpolationimg_c = cv2.resize(img, (w//2, h//2), interpolation = cv2.INTER_CUBIC)img_c = cv2.resize(img_c, (w, h), interpolation = cv2.INTER_CUBIC)

# Downscaling and upscaling using lanczos interpolationimg_l = cv2.resize(img, (w//2, h//2), interpolation = cv2.INTER_LANCZOS4)img_l = cv2.resize(img_l, (w, h), interpolation = cv2.INTER_LANCZOS4)f = plt.figure(figsize=(15,15))f.add_subplot(3, 2, 1).set_title('Original Image')plt.imshow(img[:, :, ::-1])f.add_subplot(3, 2, 2).set_title('Nearest neighbour Interpolation')plt.imshow(img_n[:, :, ::-1])f.add_subplot(3, 2, 3).set_title('Bilinear Interpolation')plt.imshow(img_b[:, :, ::-1])f.add_subplot(3, 2, 4).set_title('Area matrix Interpolation')plt.imshow(img_a[:, :, ::-1])f.add_subplot(3, 2, 5).set_title('Cubic Interpolation')plt.imshow(img_c[:, :, ::-1])f.add_subplot(3, 2, 6).set_title('Lanczos Interpolation')plt.imshow(img_l[:, :, ::-1])plt.show()

Pillow的算法

import PILimport numpy as npfrom PIL import Imagefrom matplotlib import pyplot as pltimg_p = Image.open("imgs/chapter4/tessellate.jpg")width, height = img_p.size

# Downscaling and upscaling using nearest neighbor interpolationimg_n = img_p.resize((width//2, height//2), resample=PIL.Image.NEAREST)img_n = img_n.resize((width, height), resample=PIL.Image.NEAREST)
# Downscaling and upscaling using nearest box filteringimg_f = img_p.resize((width//2, height//2), resample=PIL.Image.BOX) img_f = img_f.resize((width, height), resample=PIL.Image.BOX)

# Downscaling and upscaling using nearest Bilinear interpolationimg_b = img_p.resize((width//2, height//2), resample=PIL.Image.BILINEAR)img_b = img_b.resize((width, height), resample=PIL.Image.BILINEAR)

# Downscaling and upscaling using nearest Hamming interpolationimg_h = img_p.resize((width//2, height//2), resample=PIL.Image.HAMMING)img_h = img_h.resize((width, height), resample=PIL.Image.HAMMING)# Downscaling and upscaling using nearest Bicubic interpolationimg_c = img_p.resize((width//2, height//2), resample=PIL.Image.BICUBIC); img_c = img_c.resize((width, height), resample=PIL.Image.BICUBIC)

# Downscaling and upscaling using nearest Lanczos interpolationimg_l = img_p.resize((width//2, height//2), resample=PIL.Image.LANCZOS)img_l = img_l.resize((width, height), resample=PIL.Image.LANCZOS)

f = plt.figure(figsize=(15,20))f.add_subplot(4, 2, 1).set_title('Original Image')plt.imshow(img_p)f.add_subplot(4, 2, 2).set_title('Nearest neighbour Interpolation')plt.imshow(img_n)f.add_subplot(4, 2, 3).set_title('Box Interpolation')plt.imshow(img_f)f.add_subplot(4, 2, 4).set_title('Bilinear Interpolation')plt.imshow(img_b)f.add_subplot(4, 2, 5).set_title('Hamming Interpolation')plt.imshow(img_h)f.add_subplot(4, 2, 6).set_title('Bi-Cubic Interpolation')plt.imshow(img_c)f.add_subplot(4, 2, 7).set_title('Lanczos Interpolation')plt.imshow(img_l)plt.show()

平移

  • 在四个方向中的任何一个方向上将图像移动一定像素。

为什么要这么做?

  • 用于数据增强

使用numpy进行图像平移

import numpy as npimport cv2from matplotlib import pyplot as pltimg = cv2.imread("imgs/chapter4/dog.jpg",-1)plt.imshow(img[:,:,::-1])plt.show()

图像向右平移50像素值

h, w, c = img.shape;img_new = np.zeros((h, w, c), dtype=np.uint8);
f = plt.figure(figsize=(15,15))f.add_subplot(3, 1, 1).set_title('Original Image');plt.imshow(img[:, :, ::-1])f.add_subplot(3, 1, 2).set_title('New Blank Image');plt.imshow(img_new[:, :, ::-1])plt.show()

img_new[:, 50:, :] = img[:, :w-50, :]
plt.imshow(img_new[:,:,::-1])plt.show()

向左平移50像素值

h, w, c = img.shapeimg_new = np.zeros((h, w, c), dtype=np.uint8)
img_new[:, :w-50, :] = img[:, 50:, :]plt.imshow(img_new[:,:,::-1])plt.show()

向下平移50像素值

h, w, c = img.shape;img_new = np.zeros((h, w, c), dtype=np.uint8)
img_new[:h-50, :, :] = img[50:, :, :]plt.imshow(img_new[:,:,::-1])plt.show()

旋转

使用PIL模块旋转图像

import numpy as npfrom PIL import Imagefrom matplotlib import pyplot as pltimg_p = Image.open("imgs/chapter4/triangle.jpg")plt.imshow(img_p)plt.show()

以枢纽为中心顺时针旋转30度

img_p_new = img_p.rotate(-30)plt.imshow(img_p_new)plt.show()

以枢纽为中心逆时针旋转30度

img_p_new = img_p.rotate(30)plt.imshow(img_p_new)plt.show()

仿射变换

  • 涉及图像平移和旋转的变换。
  • 但是,变换的方式遵循图像中的直线永远不会弯曲。

使用OpenCV进行仿射变换

import numpy as npimport cv2from matplotlib import pyplot as pltimg = cv2.imread("imgs/chapter4/tessellate.jpg", -1)plt.imshow(img[:,:,::-1])plt.show()

保持两个点不变的情况下进行变换

img = cv2.imread("imgs/chapter4/tessellate.jpg", -1)rows,cols,ch = img.shape

# Read as x, ypts1 = np.float32([[50,50],[200,50], [50,200]])pts2 = np.float32([[80,50],[200,50], [50,200]])

cv2.circle(img,(int(pts1[0][0]),int(pts1[0][1])),5,(0,255,0),-1)cv2.circle(img,(int(pts1[1][0]),int(pts1[1][1])),5,(0,0,255),-1)cv2.circle(img,(int(pts1[2][0]),int(pts1[2][1])),5,(255,0,0), -1)M = cv2.getAffineTransform(pts1,pts2)dst = cv2.warpAffine(img,M,(cols,rows))
f = plt.figure(figsize=(15,15))f.add_subplot(1, 2, 1).set_title('Input')plt.imshow(img[:, :, ::-1])f.add_subplot(1, 2, 2).set_title('Transformed')plt.imshow(dst[:, :, ::-1])plt.show()

将一个点作为铰链进行变换

img = cv2.imread("imgs/chapter4/tessellate.jpg", -1)rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50], [50,200]])#pts2 = np.float32([[60,50],[190,50], [50,200]])# Works as translation + shrinkingpts2 = np.float32([[60,50],[200,50], [50,175]])

cv2.circle(img,(int(pts1[0][0]), int(pts1[0][1])), 5, (0,255,0), -1)cv2.circle(img,(int(pts1[1][0]), int(pts1[1][1])), 5, (0,0,255), -1)cv2.circle(img,(int(pts1[2][0]), int(pts1[2][1])), 5, (255,0,0), -1)
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
f = plt.figure(figsize=(15,15))f.add_subplot(1, 2, 1).set_title('Input')plt.imshow(img[:, :, ::-1])f.add_subplot(1, 2, 2).set_title('Transformed')plt.imshow(dst[:, :, ::-1])plt.show()

对三个点均进行平移-->平移

img = cv2.imread("imgs/chapter4/tessellate.jpg", -1)rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50], [50,200]])pts2 = np.float32([[60,50],[210,50], [60,200]])

cv2.circle(img,(int(pts1[0][0]), int(pts1[0][1])), 5, (0,255,0), -1)cv2.circle(img,(int(pts1[1][0]), int(pts1[1][1])), 5, (0,0,255), -1)cv2.circle(img,(int(pts1[2][0]), int(pts1[2][1])), 5, (255,0,0), -1)
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
f = plt.figure(figsize=(15,15))f.add_subplot(1, 2, 1).set_title('Input')plt.imshow(img[:, :, ::-1])f.add_subplot(1, 2, 2).set_title('Transformed')plt.imshow(dst[:, :, ::-1])plt.show()

透视变换

使用OpenCV进行透视变换

import numpy as npimport cv2from matplotlib import pyplot as pltimg = cv2.imread("imgs/chapter4/cube.png", 1)plt.imshow(img[:,:,::-1])plt.show()

放大视图

img = cv2.imread("imgs/chapter4/cube.png", 1)img = cv2.resize(img, (400, 400))rows,cols,ch = img.shape
# Counter clock wisepts1 = np.float32([[130,130],[390,75],[360,320],[140, 390]])pts2 = np.float32([[0,0],[0, 200],[200,200],[200,0]])

# uncomment each and seecv2.circle(img,(int(pts1[0][0]),int(pts1[0][1])),5,(255,255,255), -1)cv2.circle(img,(int(pts1[1][0]), int(pts1[1][1])), 5, (255,255,255), -1)cv2.circle(img,(int(pts1[2][0]), int(pts1[2][1])), 5, (255,255,255), -1)cv2.circle(img,(int(pts1[3][0]), int(pts1[3][1])), 5, (255,255,255), -1)
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(cols,rows))
f = plt.figure(figsize=(15,15))f.add_subplot(1, 2, 1).set_title('Input');plt.imshow(img[:, :, ::-1])f.add_subplot(1, 2, 2).set_title('Transformed');plt.imshow(dst[:, :, ::-1])plt.show()

DeepHub

微信号 : deephub-imba

每日大数据和人工智能的重磅干货

大厂职位内推信息

长按识别二维码关注 ->

好看就点在看!********** **********

标签:

“CV基础教程:图像上的几何变换”的评论:

还没有评论