以质量增量打包图像的算法
Posted
技术标签:
【中文标题】以质量增量打包图像的算法【英文标题】:Algorithm for packing images in increments of quality 【发布时间】:2021-09-05 18:54:23 【问题描述】:我希望将图像与“质量增量”数据包一起打包为低质量图像,以便用“质量增量”修补低质量图像可以提高其质量并使其更接近原始图像。
说得更清楚,
我想将图像打包为“基础图像”(原始图像质量较差,例如 10%),以及数据包 q1、q2、q3、...。qn
这样
base-image + q1 = original image at quality 20%
base-image + q1 + q2 = original image at quality 30%
...
base-image + q1 +q2 + .... qn = original image at quality 100%
我的要求是打包图像并通过单板计算机 (Raspberry Pi) 发送。我需要尽可能减小文件大小,但图像不应该像素化太多以至于不清楚。使用这种“增量图像质量”方法,我的想法是获得低质量的图像,并且只接收几个增量(比如直到 q3)并认为它“可以接受”,这样我就可以停止发送/接收更多数据包。
请指导我如何处理这个问题。
【问题讨论】:
通常,减小文件大小的有效方法是应用图像压缩算法。是你考虑的方式吗? ***.com/questions/2691649/… 中提到的标准。您以不断增加的分辨率加载图像,并且在分辨率/质量足够高时可能会在固定的设定时间后中止。图像加载中的挂钩也有所记录。挑战。 @Damien 是的。当我提到“降低质量”时,我想暗示“有损图像压缩”。对不起,如果我没有正确地说出来 图像的像素尺寸是多少,您有示例图像吗?我认为是接收者决定何时质量足够?我假设您在发送方和接收方之间进行双向通信?通信中存在什么样的延迟?发送者可能多久发送一次? 使用越来越高分辨率的图像的一个问题是我们得到了大量的冗余数据(基本上,一旦我们完成了一张新图像,所有以前的数据都是无用的)。我认为 OP 想要的更接近的解决方案是使用奇异值分解 (SVD) 进行图像压缩。它的压缩方案背后有一个堆叠行为,允许您将新数据添加到以前的数据中以获得更好的图像。这是这个概念的一个很好的来源:(math.utah.edu/~goller/F15_M2270/BradyMathews_SVDImage.pdf)。至少阅读第 1 节的关键点,并查看第 9 页的示例图片。 【参考方案1】:这是我在 cmets 中提到的一个快速玩具示例
原文:
以 0.2 压缩重建
import cv2
import numpy as np
# load image
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE);
height, width = img.shape[:2];
max_rank = min([width, height]);
# do svd
columns, diags, rows = np.linalg.svd(img, full_matrices = False);
# rebuild image with reduced rank
rank = int(max_rank * 0.2);
rebuilt = np.dot(columns[:,:rank] * diags[:rank], rows[:rank, :]);
rebuilt = rebuilt.astype(np.uint8)
# show image
cv2.imshow("Image", img);
cv2.imshow("Rebuilt", rebuilt);
cv2.waitKey(0);
这里的想法是您可以一次发送每一列、对角线和行。每当您决定停止等待时,您拥有的完整集数就是您将用于重建图像的等级。
一个更完整的例子
import cv2
import numpy as np
# receiver
client = [[], [], []]; # columns, diags, rows
def receive(column, value, row):
# grab global
global client;
# add new data
client[0].append(column);
client[1].append(value);
client[2].append(row);
# load image
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE);
height, width = img.shape[:2];
max_rank = min([width, height]);
# do svd
columns, diags, rows = np.linalg.svd(img, full_matrices = False);
# "send" data to client one rank at a time
for a in range(max_rank):
# check progress
print("Total Ranks Sent: " + str(a + 1));
# get a single rank
column = columns[:,a];
value = diags[a];
row = rows[a,:];
# "send" to client
receive(column, value, row);
# rebuild image with current client side data
client_cols, client_diags, client_rows = client;
# convert to numpy
client_cols = np.array(client_cols);
client_diags = np.array(client_diags);
client_rows = np.array(client_rows);
client_cols = np.transpose(client_cols);
# rebuild
rebuilt = np.dot(client_cols * client_diags, client_rows);
rebuilt = rebuilt.astype(np.uint8);
# show
cv2.imshow("Rebuilt", rebuilt);
key = cv2.waitKey(0);
# early quit
if key == ord('q'):
break;
【讨论】:
非常有趣。我尝试了您的第二段代码,在我看来,发送图像的每个等级需要传输大约 9k 字节(col
为 3600,value
为 8,row
为 5400)。那是对的吗?我只能猜测它是 4 级的向日葵,toto 为 36kB。质量为 5 的 JPEG 为 5kB,看起来有点“更好”,质量为 10 的 JPEG 大约为 11kB,甚至更好。还是我没有比较喜欢和喜欢?
大声笑,你是对的。我什至没有想过一堆浮点数可以有多大。这绝对是一个幼稚的实现。我不是信息论专家;我从头开始编写的任何代码都无法接近成熟的压缩算法。你必须环顾四周才能找到这个想法的真正实现。以上是关于以质量增量打包图像的算法的主要内容,如果未能解决你的问题,请参考以下文章
基于nsct变换特征提取和模糊神经网络的无参考图像质量评价算法matlab仿真