分类 代码与算法 下的文章

整体流程图

lzl71npw.png

键盘示意图

lzl78l51.png

视频演示

https://www.bilibili.com/video/BV1euYxeBEDK/

代码调用说明

// 初始化时调用(重要!!!):
KeyBoard_Init();

// 在定时器中调用(重要!!!):
if(AllowKeyBoardTouch) KeyBoard_Select();

// 需要使用键盘时调用:
Show_KeyBoard();

// 退出使用键盘时调用:
Hide_KeyBoard();

C代码参考

lzl769zc.png

lzl754sa.png

文件下载

{hide}
keyboard.zip
{/hide}


转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn]

透视变换矩阵计算:
http://jlouthan.github.io/perspective-transform/examples/test-ui/index.html

效果演示

以这个图为例:

需要调用的函数为:

def warpImage(src, theta, phi, gamma, scale, fovy, corners=None):
  '''
  src: 待处理的图像
  theta, phi, gamma: 三个方位角
  scale: 缩放值
  fovy: 相机的FOV
  corners: 图像中待处理目标的四个角的坐标,暂未用到
  '''
  pass

当取值theta=30, phi=0, gamma=0, scale=1.0, fovy=83时候:
lbrp2k8s.png

当取值theta=0, phi=30, gamma=0, scale=1.0, fovy=83时候:
lbrp92at.png

当取值theta=30, phi=30, gamma=0, scale=1.0, fovy=83时候:
lbrp9opd.png

更多的不再演示。

{dotted startColor="#ff6c6c" endColor="#1989fa"/}

Python代码

{hide}

import cv2
import matplotlib.pyplot as plt
import numpy as np
from functools import reduce

# Construct 3D rotation matrix when rotations around x,y,z axes are specified
def construct_RotationMatrixHomogenous(rotation_angles):
    assert (type(rotation_angles) == list and len(rotation_angles) == 3)
    RH = np.eye(4, 4)
    cv2.Rodrigues(np.array(rotation_angles), RH[0:3, 0:3])
    return RH

# https://en.wikipedia.org/wiki/Rotation_matrix
def getRotationMatrixManual(rotation_angles):
    rotation_angles = list(map(lambda x: np.deg2rad(x), rotation_angles))

    phi = rotation_angles[0]  # around x
    gamma = rotation_angles[1]  # around y
    theta = rotation_angles[2]  # around z

    # X rotation
    Rphi = np.eye(4, 4)
    sp = np.sin(phi)
    cp = np.cos(phi)
    Rphi[1, 1] = cp
    Rphi[2, 2] = Rphi[1, 1]
    Rphi[1, 2] = -sp
    Rphi[2, 1] = sp

    # Y rotation
    Rgamma = np.eye(4, 4)
    sg = np.sin(gamma)
    cg = np.cos(gamma)
    Rgamma[0, 0] = cg
    Rgamma[2, 2] = Rgamma[0, 0]
    Rgamma[0, 2] = sg
    Rgamma[2, 0] = -sg

    # Z rotation (in-image-plane)
    Rtheta = np.eye(4, 4)
    st = np.sin(theta)
    ct = np.cos(theta)
    Rtheta[0, 0] = ct
    Rtheta[1, 1] = Rtheta[0, 0]
    Rtheta[0, 1] = -st
    Rtheta[1, 0] = st

    R = reduce(lambda x, y: np.matmul(x, y), [Rphi, Rgamma, Rtheta])
    return R

def getPoints_for_PerspectiveTranformEstimation(ptsIn, ptsOut, W, H, sidelength):
    ptsIn2D = ptsIn[0, :]
    ptsOut2D = ptsOut[0, :]
    ptsOut2Dlist = []
    ptsIn2Dlist = []

    for i in range(0, 4):
        ptsOut2Dlist.append([ptsOut2D[i, 0], ptsOut2D[i, 1]])
        ptsIn2Dlist.append([ptsIn2D[i, 0], ptsIn2D[i, 1]])

    pin = np.array(ptsIn2Dlist) + [W / 2., H / 2.]
    pout = (np.array(ptsOut2Dlist) + [1., 1.]) * (0.5 * sidelength)
    pin = pin.astype(np.float32)
    pout = pout.astype(np.float32)

    return pin, pout

def warpMatrix(W, H, theta, phi, gamma, scale, fV):
    # M is to be estimated
    M = np.eye(4, 4)

    fVhalf = np.deg2rad(fV / 2.)
    d = np.sqrt(W * W + H * H)
    sideLength = scale * d / np.cos(fVhalf)
    h = d / (2.0 * np.sin(fVhalf))
    n = h - (d / 2.0)
    f = h + (d / 2.0)

    # Translation along Z-axis by -h
    T = np.eye(4, 4)
    T[2, 3] = -h

    # Rotation matrices around x,y,z
    R = getRotationMatrixManual([phi, gamma, theta])

    # Projection Matrix 
    P = np.eye(4, 4)
    P[0, 0] = 1.0 / np.tan(fVhalf)
    P[1, 1] = P[0, 0]
    P[2, 2] = -(f + n) / (f - n)
    P[2, 3] = -(2.0 * f * n) / (f - n)
    P[3, 2] = -1.0

    # pythonic matrix multiplication
    F = reduce(lambda x, y: np.matmul(x, y), [P, T, R])

    # 对于ptsIn和ptsOut, shape应该是1,4,3,因为perspectiveTransform()期望这样的数据。  
    # 在c++中,可通过Mat ptsIn(1,4,CV_64FC3)实现;  
    ptsIn = np.array([[
        [-W / 2., H / 2., 0.], [W / 2., H / 2., 0.], [W / 2., -H / 2., 0.], [-W / 2., -H / 2., 0.]
    ]])
    ptsOut = np.array(np.zeros((ptsIn.shape), dtype=ptsIn.dtype))
    ptsOut = cv2.perspectiveTransform(ptsIn, F)

    ptsInPt2f, ptsOutPt2f = getPoints_for_PerspectiveTranformEstimation(ptsIn, ptsOut, W, H, sideLength)

    # check float32 otherwise OpenCV throws an error
    assert (ptsInPt2f.dtype == np.float32)
    assert (ptsOutPt2f.dtype == np.float32)
    M33 = cv2.getPerspectiveTransform(ptsInPt2f, ptsOutPt2f)

    return M33, sideLength

def warpImage(src, theta, phi, gamma, scale, fovy, corners=None):
    '''
    src: 待处理的图像
    theta, phi, gamma: 三个方位角
    scale: 缩放值
    fovy: 相机的FOV
    corners: 图像中待处理目标的四个角的坐标,暂未用到
    '''
    H, W, Nc = src.shape
    M, sl = warpMatrix(W, H, theta, phi, gamma, scale, fovy)  # 计算变形矩阵
    sl = int(sl)
    print('Output image dimension = {}'.format(sl))
    print('Output M = {}'.format(M))
    dst = cv2.warpPerspective(src, M, (sl, sl))  # 进行图像扭曲
    return dst


src = cv2.imread('test.jpg')
src = src[..., ::-1]  # BGR to RGB
H, W, Nc = src.shape
imgwarped = warpImage(src, 30, 30, 0, 1., 83)
plt.imshow(imgwarped)

plt.show()

{/hide}



直接在缓存中互读

import io
import numpy as np
import PIL
import matplotlib.pyplot as plt
 
#... fig = ...
#假设你有了一个绘图结果fig
 
#申请缓存
buffer_ = io.BytesIO()
fig.savefig(buffer_, format = "png")
buffer_.seek(0)
image = PIL.Image.open(buffer_)
#转换为numpy array
ar = np.asarray(image)
cv2.imshow("demo", ar)
#释放缓存
buffer_.close()

来源:https://blog.csdn.net/ngy321/article/details/80109088

OpenCV添加文字

cv2.putText(img, text, (40, 50), cv2.FONT_HERSHEY_PLAIN, 2.0, (0, 0, 255), 2)

格式互转

opencv默认BGR顺序,matplotlib和PIL默认RGB顺序。

# Image转cv2
cv2_img = cv2.cvtColor(numpy.asarray(Img_img),cv2.COLOR_RGB2BGR)

# cv2转Image
pil_img = Image.fromarray(cv2.cvtColor(cv_img,cv2.COLOR_BGR2RGB))

隐藏坐标轴文本刻度或刻度标签

# 隐藏包括轴标签的坐标轴
xaxis.set_visible(False)/yaxis.set_visible(False)
# 在 Matplotlib 中隐藏坐标轴
xaxis.set_ticks([])/yaxis.set_ticks([]) 
# 在 Matplotlib 中隐藏轴标签/文本
xaxis.set_ticklabels([])/yaxis.set_ticklabels([]) 
# 来隐藏 Matplotlib 中的坐标轴标签/文本
xticks(color='w')/yticks(color='w') 

来源:https://www.delftstack.com/zh/howto/matplotlib/how-to-hide-axis-text-ticks-and-or-tick-labels-in-matplotlib/

关闭1个fig

plt.close(fig)

保存时去除白边

# pad_inches=0:去除所有白边
# bbox_inches='tight':去除坐标轴占用的空间
plt.savefig(path, format='png', pad_inches=0, bbox_inches='tight')

调整图片间隙

fig.tight_layout()  # 调整整体空白
plt.subplots_adjust(wspace=0, hspace=0)  # 调整子图间距
plt.subplot_tool() # 提供了一种交互式方法来拖动 subplot_tool 中的条以更改子图的布局

取消边框

axes[i][j].spines['top'].set_visible(False)
axes[i][j].spines['right'].set_visible(False)
axes[i][j].spines['bottom'].set_visible(False)
axes[i][j].spines['left'].set_visible(False)
````

## 生成空白图

使用Numpy创建一张A4(2105×1487)纸

格式:h,w,c

img = np.zeros((2105,1487,3), np.uint8)

使用白色填充图片区域,默认为黑色

img.fill(255)


## 显示中文

plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False #该语句解决图像中的“-”负号的乱码问题


## 显示双坐标

fig, axes = plt.subplots(nrows=3, ncols=3)

坐标1

axes0.set_title('aaa', fontsize=17)
axes0.set_xlim(0, len(all_algs)+1)
axes0.set_xticks(range(1, 10))
axes0.set_ylim(0, 105)
axes0.grid(True)

坐标2(子坐标)

ax2 = axes0.twinx()

具体用法跟上面一样

ax2.set_ylabel('Number')
ax2.set_ylim(0, 5)
ax2.bar(x, fine, color='b', alpha=0.4, width=0.4, label=alg)
ax2.legend(prop={'size': 11}, loc="upper right" , labelcolor='linecolor')


## 坐标显示中文

axes0.set_xticks([1, 2, 3], ['a', 'b', 'c'])


## 坐标轴倾斜

axes0.set_xticklabels(all_algs, rotation=15)


## 坐标轴显示分式
latex语法即可

axes.set_xlabel(r'aaa ($\frac{x}{y}$)', fontsize=16)


import

from tqdm import tqdm

tqdm + for + range

for i, line in tqdm(range(10)):
    # xxxxxxx
    pass

tqdm + enumerate

for i, line in enumerate(tqdm(f)):
    # xxxxxxx
    pass

tqdm + enumerate + file

num_lines = sum(1 for line in open(file_path, 'r'))
with open(file_path) as f:
    for i, line in enumerate(tqdm(f, total=num_lines)):
        # xxxxxxx
        pass