图像旋转后出现黑点 - - 填坑

Posted adjwang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图像旋转后出现黑点 - - 填坑相关的知识,希望对你有一定的参考价值。

前接:图像旋转后出现黑点 - (一) - 入坑

这是填坑篇,之前写的图片旋转程序把图片变成了桌布,几个世纪后,在一个月黑风高的夜晚,我灵光乍现,何不试试双线性插值?

先上代码和效果图。

 1 # !/usr/bin/env python3
 2 # -*-coding:utf-8-*-
 3 """ 
 4 双线性插值参考资料: 双线性插值原理及Python实现 - Jinglever  https://www.jianshu.com/p/29e5c84ea539
 5 
 6 如果出现错误:...If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config
 7 执行 pip3 install opencv-contrib-python
 8 """
 9 import numpy as np
10 # np.set_printoptions(suppress=True)    # 关闭科学计数法
11 import cv2
12 import os
13 
14 
15 # 旋转矩阵R
16 ANGLE = 30  # (dim=°)
17 assert 0 < ANGLE < 90   # 目前限制这个旋转范围,原因是y1, y2, y3, y4上下关系根据角度变化
18 alpha = ANGLE/360*2*np.pi
19 R_rev = np.matrix([[np.cos(alpha), np.sin(alpha)],      # 逆向映射推导的旋转矩阵
20                 [-np.sin(alpha), np.cos(alpha)]])
21 print(R_rev)
22 
23 # 重设图片大小
24 WIDTH, HEIGHT = 640, 480
25 
26 img = cv2.imread("timg.jpg")
27 img = cv2.resize(img, (WIDTH, HEIGHT))
28 # img_gray = np.float32(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))
29 img = np.float32(img)
30 print(img.shape)
31 
32 # 假设已经得到旋转后的图片,利用图片边框画出图片的矩形,在矩形内遍历坐标就是图片各个像素点的坐标
33 # 注意旋转角度超过90度后边框线的上下关系会发生变化,待改进……
34 x = np.arange(np.abs(WIDTH*np.cos(alpha)) + np.abs(HEIGHT*np.sin(alpha)), dtype=np.int32)
35 y1 = lambda x: (- x*np.tan(alpha)).astype(np.int32)
36 y2 = lambda x: (y1(x) + HEIGHT/np.cos(alpha)).astype(np.int32)
37 y3 = lambda x: (x/np.tan(alpha)).astype(np.int32)
38 y4 = lambda x: (y3(x) - WIDTH/np.sin(alpha)).astype(np.int32)
39 # 用矩形下面2条线(的最大值)确定y坐标最小值,上面2条线(的最小值)确定y坐标最大值
40 y_min = np.max(np.concatenate((y1(x).reshape(1, -1), y4(x).reshape(1, -1))), axis=0)
41 y_max = np.min(np.concatenate((y2(x).reshape(1, -1), y3(x).reshape(1, -1))), axis=0)
42 # 计算旋转后图片各像素点坐标
43 pre_index = [np.array((yi, xi)).reshape(-1, 1) for xi in x for yi in range(y_min[xi], y_max[xi]+1)]
44 
45 ori_index = np.array(list(map(R_rev.dot, pre_index))).reshape(-1, 2)     # 坐标变换到原图
46 hs_p, ws_p = np.hsplit(ori_index, 2) # 分离y, x坐标
47 
48 ws_p = np.clip(ws_p, 0, WIDTH-1)  # 限制坐标最值防止越界
49 hs_p = np.clip(hs_p, 0, HEIGHT-1)
50 
51 ws_0 = np.clip(np.floor(ws_p), 0, WIDTH - 2).astype(np.int)     # 找出每个投影点在原图的近邻点坐标
52 hs_0 = np.clip(np.floor(hs_p), 0, HEIGHT - 2).astype(np.int)
53 ws_1 = ws_0 + 1
54 hs_1 = hs_0 + 1
55 
56 f_00 = img[hs_0, ws_0, :].T    # 四个临近点的像素值
57 f_01 = img[hs_0, ws_1, :].T
58 f_10 = img[hs_1, ws_0, :].T
59 f_11 = img[hs_1, ws_1, :].T
60 
61 w_00 = ((hs_1 - hs_p) * (ws_1 - ws_p)).T    # 计算权重
62 w_01 = ((hs_1 - hs_p) * (ws_p - ws_0)).T
63 w_10 = ((hs_p - hs_0) * (ws_1 - ws_p)).T
64 w_11 = ((hs_p - hs_0) * (ws_p - ws_0)).T
65 
66 pixels = (f_00 * w_00).T + (f_01 * w_01).T + (f_10 * w_10).T + (f_11 * w_11).T  # 计算目标像素值
67 
68 y_new, x_new = np.hsplit(np.array(pre_index).reshape(-1, 2), 2) # # 分离y, x坐标
69 y_new = y_new - np.min(y_new)      # y坐标平移,防止图片旋转后被窗口切分
70 
71 h, w = np.max(y_new), np.max(x_new)    # 旋转后画布大小
72 # 像素映射 原始→新图
73 new_img = np.zeros((h+1, w+1, img.shape[2]))    # (H, W, C)
74 new_img[y_new, x_new, :] = pixels   # 填充像素
75 
76 cv2.imwrite(./AffinedImg.jpg, new_img, [int(cv2.IMWRITE_JPEG_QUALITY),95])
77 # 显示图片
78 cv2.imshow(img, np.array(new_img, dtype=np.uint8))
79 cv2.waitKey(0)
80 cv2.destroyAllWindows()

原图见入坑篇。

下面是运行结果,这次我换成了彩色的:

技术图片

 

 ...讲解?最近忙成球,正在紧张编辑中,敬请期待……;-)

以上是关于图像旋转后出现黑点 - - 填坑的主要内容,如果未能解决你的问题,请参考以下文章

导航后未附加回收站视图

matlab图像旋转怎么操作?

Butterknife 片段旋转给出 NullPointer

旋转后Python PIL保存图像

旋转后片段字段为空

图像全景拼接黑点