直接在缓存中互读

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


网上找了好久没找到能用的,索性自己写个来的更快。。。
方法比较粗暴,没咋细究,若有bug欢迎留言~~

需求:

  • NMS中的IOU相关,是选择一个最大或者可信度最高的框框保留。
  • 而我们现在试需要将重叠框框合并为一个大的框框,所以不能直接用上面的。
  • 并且OpenCV的groupRectangles在Python中我实在用不懂,而且它会把不重叠的框直接删了。。

原理:

  • 循环+递归,依次判断两个框是否有重叠。

效果

参考代码:

import cv2
import numpy as np


def checkOverlap(boxa, boxb):
    x1, y1, w1, h1 = boxa
    x2, y2, w2, h2 = boxb
    if (x1 > x2 + w2):
        return 0
    if (y1 > y2 + h2):
        return 0
    if (x1 + w1 < x2):
        return 0
    if (y1 + h1 < y2):
        return 0
    colInt = abs(min(x1 + w1, x2 + w2) - max(x1, x2))
    rowInt = abs(min(y1 + h1, y2 + h2) - max(y1, y2))
    overlap_area = colInt * rowInt
    area1 = w1 * h1
    area2 = w2 * h2
    return overlap_area / (area1 + area2 - overlap_area)

def unionBox(a, b):
    x = min(a[0], b[0])
    y = min(a[1], b[1])
    w = max(a[0] + a[2], b[0] + b[2]) - x
    h = max(a[1] + a[3], b[1] + b[3]) - y
    return [x, y, w, h]

def intersectionBox(a, b):
    x = max(a[0], b[0])
    y = max(a[1], b[1])
    w = min(a[0] + a[2], b[0] + b[2]) - x
    h = min(a[1] + a[3], b[1] + b[3]) - y
    if w < 0 or h < 0:
        return ()
    return [x, y, w, h]

def rectMerge_sxf(rects: []):
    # rects => [[x1, y1, w1, h1], [x2, y2, w2, h2], ...]
    '''
    当通过connectedComponentsWithStats找到rects坐标时,
    注意前2個坐标是表示整個圖的,需要去除,不然就只有一個大框,
    在执行此函数前,可执行类似下面的操作。
    rectList = sorted(rectList)[2:]
    '''
    rectList = rects.copy()
    rectList.sort()
    new_array = []
    complete = 1
    # 要用while,不能forEach,因爲rectList內容會變
    i = 0
    while i < len(rectList):
        # 選後面的即可,前面的已經判斷過了,不需要重復操作
        j = i + 1
        succees_once = 0
        while j < len(rectList):
            boxa = rectList[i]
            boxb = rectList[j]
            # 判斷是否有重疊,注意只針對水平+垂直情況,有角度旋轉的不行
            if checkOverlap(boxa, boxb):  # intersectionBox(boxa, boxb)
                complete = 0
                # 將合並後的矩陣加入候選區
                new_array.append(unionBox(boxa, boxb))
                succees_once = 1
                # 從原列表中刪除,因爲這兩個已經合並了,不刪除會導致重復計算
                rectList.remove(boxa)
                rectList.remove(boxb)
                break
            j += 1
        if succees_once:
            # 成功合並了一次,此時i不需要+1,因爲上面進行了remove(boxb)操作
            continue
        i += 1
    # 剩餘項是不重疊的,直接加進來即可
    new_array.extend(rectList)

    # 0: 可能還有未合並的,遞歸調用;
    # 1: 本次沒有合並項,說明全部是分開的,可以結束退出
    if complete == 0:
        complete, new_array = rectMerge_sxf(new_array)
    return complete, new_array


box = [[20, 20, 20, 20], [100, 100, 100, 100], [60, 60, 50, 50], [50, 50, 50, 50]]
_, res = rectMerge_sxf(box)
print(res)
print(box)

img = np.ones([256, 256, 3], np.uint8)
for x,y,w,h in box:
    img = cv2.rectangle(img, (x,y), (x+w,y+h), (0, 255, 0), 2)
cv2.imshow('origin', img)

img = np.ones([256, 256, 3], np.uint8)
for x,y,w,h in res:
    img = cv2.rectangle(img, (x,y), (x+w,y+h), (0, 0, 255), 2)
cv2.imshow('after', img)

cv2.waitKey(0)


源码地址:https://github.com/cvg/Hierarchical-Localization/


在本笔记本中,我们将从一小组图像建立一个场景的3D地图,然后本地化从互联网下载的图像。 本演示由Philipp Lindenberger贡献。

%load_ext autoreload
%autoreload 2
import tqdm, tqdm.notebook
tqdm.tqdm = tqdm.notebook.tqdm  # notebook-friendly progress bars
from pathlib import Path

from hloc import extract_features, match_features, reconstruction, visualization, pairs_from_exhaustive
from hloc.visualization import plot_images, read_image
from hloc.utils import viz_3d

设置

这里我们定义了一些输出路径。

images = Path('datasets/sacre_coeur')
outputs = Path('outputs/demo/')
!rm -rf $outputs
sfm_pairs = outputs / 'pairs-sfm.txt'
loc_pairs = outputs / 'pairs-loc.txt'
sfm_dir = outputs / 'sfm'
features = outputs / 'features.h5'
matches = outputs / 'matches.h5'

feature_conf = extract_features.confs['superpoint_aachen']
matcher_conf = match_features.confs['superglue']

3D映射

首先,我们列出用于映射的图像。 这些都是白天拍摄的圣心大教堂。

references = [str(p.relative_to(images)) for p in (images / 'mapping/').iterdir()]
print(len(references), "mapping images")
plot_images([read_image(images / r) for r in references[:4]], dpi=50)

然后我们提取特征并在图像对之间进行匹配。 由于我们处理的图像很少,所以我们只是竭尽所能地匹配所有对。 对于更大的场景,我们将使用图像检索,正如在其他笔记本中演示的那样。

extract_features.main(feature_conf, images, image_list=references, feature_path=features)
pairs_from_exhaustive.main(sfm_pairs, image_list=references)
match_features.main(matcher_conf, sfm_pairs, features=features, matches=matches);


在此基础上,进行Structure-From-Motion和显示重建的三维模型。

model = reconstruction.main(sfm_dir, images, sfm_pairs, features, matches, image_list=references)
fig = viz_3d.init_figure()
viz_3d.plot_reconstruction(fig, model, color='rgba(255,0,0,0.5)', name="mapping")
fig.show()



我们还可视化那些被三角化到3D模型中的关键点。

visualization.visualize_sfm_2d(model, images, color_by='visibility', n=2)

定位

现在我们有了场景的3D地图,我们可以定位任何图像。 为了证明这一点,我们从维基媒体下载了一张夜间图片(https://commons.wikimedia.org/wiki/File:Paris_-_Basilique_du_Sacr%C3%A9_Coeur,_Montmartre_-_panoramio.jpg)。

url = "https://upload.wikimedia.org/wikipedia/commons/5/53/Paris_-_Basilique_du_Sacr%C3%A9_Coeur%2C_Montmartre_-_panoramio.jpg"
# try other queries by uncommenting their url
# url = "https://upload.wikimedia.org/wikipedia/commons/5/59/Basilique_du_Sacr%C3%A9-C%C5%93ur_%285430392880%29.jpg"
# url = "https://upload.wikimedia.org/wikipedia/commons/8/8e/Sacr%C3%A9_C%C5%93ur_at_night%21_%285865355326%29.jpg"
query = 'query/night.jpg'
#!mkdir -p $images/query && wget $url -O $images/$query -q
plot_images([read_image(images / query)], dpi=75)

同样,我们为查询提取特征并全力匹配它们。

extract_features.main(feature_conf, images, image_list=[query], feature_path=features, overwrite=True)
pairs_from_exhaustive.main(loc_pairs, image_list=[query], ref_list=references)
match_features.main(matcher_conf, loc_pairs, features=features, matches=matches, overwrite=True);

我们读取query的EXIF数据来推断相机参数(如焦距)的粗略初始估计。 然后利用PnP+RANSAC估计相机的绝对位姿,并对相机参数进行优化。

import pycolmap
from hloc.localize_sfm import QueryLocalizer, pose_from_cluster

camera = pycolmap.infer_camera_from_image(images / query)
ref_ids = [model.find_image_with_name(r).image_id for r in references]
conf = {
    'estimation': {'ransac': {'max_error': 12}},
    'refinement': {'refine_focal_length': True, 'refine_extra_params': True},
}
localizer = QueryLocalizer(model, conf)
ret, log = pose_from_cluster(localizer, query, camera, ref_ids, features, matches)

print(f'found {ret["num_inliers"]}/{len(ret["inliers"])} inlier correspondences.')
visualization.visualize_loc_from_log(images, query, log, model)

我们将查询图像和一些映射图像之间的对应关系可视化。 我们也可以在3D地图中可视化估计的相机姿态。

pose = pycolmap.Image(tvec=ret['tvec'], qvec=ret['qvec'])
viz_3d.plot_camera_colmap(fig, pose, camera, color='rgba(0,255,0,0.5)', name=query)
fig.show()