图像中部分RGB矩阵可视化

图像中部分RGB可视化

今天室友有个需求就是模仿下面这张图画个示意图:

图像中部分RGB矩阵可视化_第1张图片

大致就是把图像中的一小部分区域的RGB值可视化了一下。他居然不知道该怎么画,我寻思这不直接秒了。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


class Plotter:
    def __init__(self, img):
        self.img = img
        self.range = None

        # 三个图的位置
        self.loc = [
            [0.01, 0.325, 0.35, 0.35],
            [0.375, 0.375, 0.25, 0.25],
            [0.71, 0.355, 0.29, 0.29],
        ]
        self.dloc = [0.02, 0.02]  # 表格间距
        self.facecolor = plt.get_cmap("Accent")(range(3))  # 表格颜色

    def plot_img(self, fig):
        img_range = self.range
        axes = fig.add_axes(self.loc[0])
        axes.imshow(self.img, aspect="auto")
        axes.add_patch(
            plt.Rectangle(
                (img_range[0], img_range[2]),
                img_range[1] - img_range[0],
                img_range[3] - img_range[2],
                fill=False,
                edgecolor="red",
                linewidth=2,
            )
        )
        axes.axis("off")

    def plot_table(self, fig, table):
        loc = self.loc[2]
        dloc = self.dloc
        facecolor = self.facecolor

        for i in range(table.shape[2]):
            axes = fig.add_axes(
                [loc[0] - dloc[0] * i, loc[1] - dloc[1] * i, loc[2], loc[3]],
            )
            axes.table(
                cellText=table[:, :, i],
                loc="center",
                cellColours=np.full(
                    (table.shape[0], table.shape[1], 4),
                    facecolor[i],
                    dtype=self.facecolor[0].dtype,
                ),
                bbox=[0, 0, 1, 1],
            )
            axes.axis("off")

    def plot_range_img(self, fig, range_img):
        axes = fig.add_axes(self.loc[1])
        axes.imshow(range_img, aspect="auto")

        axes.set_xticks([])
        axes.set_yticks([])
        spines = ["left", "right", "bottom", "top"]
        for spine in spines:
            axes.spines[spine].set_color("r")

    def plot_path(self, axes, x1, x2):
        x = np.linspace(x1[0], x2[0], 100)
        y = np.linspace(x1[1], x2[1], 100)
        axes.set_xlim(0, 1)
        axes.set_ylim(0, 1)
        axes.plot(x, y, "r--")

    def range_points_on_img(self):
        img_range = self.range
        loc = self.loc[0]
        luloc = loc[0] + img_range[0] / self.img.shape[0] * loc[2]
        # axes坐标系y轴方向相反
        ldloc = loc[1] + (self.img.shape[1] - img_range[2]) / self.img.shape[1] * loc[3]
        dx = (img_range[1] - img_range[0]) / self.img.shape[0] * loc[2]
        dy = (img_range[3] - img_range[2]) / self.img.shape[1] * loc[3]
        return [(luloc + dx, ldloc - dy), (luloc + dx, ldloc)]

    def plot_img2range(self, axes):
        img_points = self.range_points_on_img()
        range_points = [
            (self.loc[1][0], self.loc[1][1]),
            (self.loc[1][0], self.loc[1][1] + self.loc[1][3]),
        ]
        print(img_points)
        self.plot_path(axes, img_points[0], range_points[0])
        self.plot_path(axes, img_points[1], range_points[1])

    def plot_range2table(self, axes):
        range_points = [
            (self.loc[1][0] + self.loc[1][2], self.loc[1][1]),
            (self.loc[1][0] + self.loc[1][2], self.loc[1][1] + self.loc[1][3]),
        ]
        table_points = [
            (self.loc[2][0] - self.dloc[0] * 2, self.loc[2][1] - self.dloc[1] * 2),
            (
                self.loc[2][0] - self.dloc[0] * 2,
                self.loc[2][1] + self.loc[2][3] - self.dloc[1] * 2,
            ),
        ]
        self.plot_path(axes, range_points[0], table_points[0])
        self.plot_path(axes, range_points[1], table_points[1])

    def plot_line(self, fig):
        axes = fig.add_axes([0, 0, 1, 1])
        self.plot_img2range(axes)
        self.plot_range2table(axes)
        axes.axis("off")

    def plot(self, img_range):
        self.range = img_range
        range_img = self.img[
            img_range[0] : img_range[1], img_range[2] : img_range[3], :
        ]
        fig = plt.figure()
        self.plot_img(fig)
        self.plot_range_img(fig, range_img)
        self.plot_table(fig, range_img)
        self.plot_line(fig)
        plt.show()


if __name__ == "__main__":
    img_path = "lena_color_512.tif"
    img = cv.imread(img_path, cv.IMREAD_UNCHANGED)
    img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    p = Plotter(img)
    p.plot([255, 265, 255, 265])

其实就是先画三个主图,一个全部的,一个小范围内的,一个RGB值的表,然后画四根线就完事了。效果如下:

图像中部分RGB矩阵可视化_第2张图片

唯一要注意的是 Axes 坐标系和图像的坐标系中Y轴是相反的,然后其他 axes.imshowaxes.table 都让它填满整个 Axes 就好了,要不然它给你自适应了,不好算几根连线的位置。

这里写的时候没想好,按 copilot 生成的 img_range 形式写下去了,目前是 [x起点,x终点,y起点,y终点] 的格式,换成 [x起点,y起点,x范围,y范围] 会更统一一点。但也懒得改了,一小时的工作时间白嫖室友一顿必胜客,很舒服。

你可能感兴趣的:(杂,数据可视化,图像处理)