python - matplotlib选择图像的框区域然后放大

标签 python opencv matplotlib

使用 opencv 从网络摄像头获取帧,然后绘制它。 我在图的中心画了一个矩形,然后得到选中的区域并显示在另一个图中(通过插值放大)

import matplotlib.pyplot as plt
import matplotlib.animation as animation

import cv2

boxSize = 150
enlargeBy = 3

def getBoxCoordinates(cap, size):
    width = cap.get(3)
    height = cap.get(4)
    x1 = int(width / 2) - int(size / 2)
    y1 = int(height / 2) - int(size / 2)
    x2 = int(width / 2) + int(size / 2)
    y2 = int(height / 2) + int(size / 2)

    return [(x1, y1), (x2, y2)]

def getBox(cap, boxSize, frame, enlargeBy):
    [(x1, y1), (x2, y2)] = getBoxCoordinates(cap, boxSize);

    # Get pixels in box
    box_img = frame[y1 + 1:y2, x1 + 1:x2]  # +1 cuz it excludes initial pixel interval
    return cv2.resize(box_img, None, fx=enlargeBy, fy=enlargeBy,
                      interpolation=cv2.INTER_LINEAR)  # different interpolation methods

cap = cv2.VideoCapture(0);
ret, frame = cap.read()

figWidth = 20
figHeight = 8
fig = plt.figure(figsize=(figWidth, figHeight))


enlarged = getBox(cap, boxSize, frame, enlargeBy)
[(x1, y1), (x2, y2)] = getBoxCoordinates(cap, boxSize);
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), lineType=1)


video_plot = plt.subplot2grid((figHeight, figWidth), (0, 0), colspan=4, rowspan=4)
video_plot.axis('off')
video_plot.set_title("Camera feed")
video = video_plot.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))


box_plot = plt.subplot2grid((figHeight, figWidth), (0, 4), colspan=4, rowspan=4)
box_plot.axis('off')
box_plot.set_title("Box")
box = box_plot.imshow(cv2.cvtColor(enlarged, cv2.COLOR_BGR2RGB)) #frame just to start


def updatefig(i):
    ret, frame = cap.read()
    cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), lineType=1)

    enlarged = getBox(cap, boxSize, frame, enlargeBy)

    video.set_data(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    box.set_data(cv2.cvtColor(enlarged, cv2.COLOR_BGR2RGB))

    return [video, box]

ani = animation.FuncAnimation(fig, updatefig, interval=20, frames=200, blit=True)

plt.tight_layout()
plt.show()


cv2.destroyAllWindows()


plt.show()

我遇到的奇怪问题是我在框架上绘制的矩形没有正确显示:它只显示一个或几个边。 我注意到当图形尺寸发生变化时,这种情况会发生变化,例如使用上面的代码,如果我更改,它只会显示底部和左侧:

figWidth = 10

然后我看到底部、右侧和顶部,但看不到左侧。

不知道究竟是什么导致了这个以及如何解决。

最佳答案

cv2.rectangle 被绘制为图像中的像素。现在的问题是您可能在图像中有更多的像素,您可以使用 imshow 绘图在屏幕上显示这些像素。例如。在 cv 图像中有 1200 像素,并在屏幕上以 300 像素显示此图像需要 matplotlib 将 4 个真实像素插入 1 个屏幕像素,从而有 75% 的机会丢失您想要显示的像素。

显而易见的解决方案是使矩形的线条更粗。

cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), thickness=3)

然而,这会产生副作用,使放大图片中的矩形线也出现:

enter image description here

因此,另一种选择可能是在 imshow 图的顶部使用 matplotlib 绘制矩形。这个矩形只需要绘制一次,但需要是 updatefig 返回列表的一部分。

...
video = video_plot.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
rectangle = plt.Rectangle((x1,y1), x2-x1, y2-y1, edgecolor="gold", fill=False)
video_plot.add_patch(rectangle)
...

def updatefig(i):
    ret, frame = cap.read()
    enlarged = getBox(cap, boxSize, frame, enlargeBy)
    video.set_data(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    box.set_data(cv2.cvtColor(enlarged, cv2.COLOR_BGR2RGB))
    return [video, box, rectangle]

enter image description here

关于python - matplotlib选择图像的框区域然后放大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43793498/

相关文章:

grid - 通过网格在Tkinter中显示Matplotlib导航工具栏

python - 如何在 django 表单中以列表形式输入数据?

python - 同时有效地获取 numpy.argmin 和 numpy.amin

python - 如何找到python库路径?

python - 调整单个子图宽度的简单方法?

python - 使用 Python 高效地绘制 csv 格式的表格

python - 如何修复在 Flask-uwsgi-Nginx 设置中被 Post 请求延迟的 websocket 消息?

python - OpenCV restorePose相机坐标系

video - OpenCV - 是否需要 .clone() 函数来双重缓冲视频源?

python - 制作由掩码选择的像素列表