首页 > 编程问答 >在质量和文件大小之间进行折衷,如何将非常详细的图像保存到合理大小(<1MB)的文件中?

在质量和文件大小之间进行折衷,如何将非常详细的图像保存到合理大小(<1MB)的文件中?

时间:2024-07-21 12:18:39浏览次数:16  
标签:python opencv image-processing

我面临一个小(大)问题:我想生成高分辨率散斑图案并将其保存为可以导入激光雕刻机的文件。可以是 PNG、JPEG、PDF、SVG 或 TIFF。

我的脚本很好地生成了我想要的模式:

用户需要首先定义输入,这些是:

############
#  INPUTS  #
############
dpi = 1000 # dots per inch
dpmm = 0.03937 * dpi # dots per mm
widthOfSampleMM = 50 # mm
heightOfSampleMM = 50 # mm
patternSizeMM = 0.1 # mm
density = 0.75 # 1 is very dense, 0 is not fine at all
variation = 0.75 # 1 is very bad, 0 is very good
############

之后,我生成空矩阵并用黑色形状填充它,在本例中是一个圆圈。

# conversions to pixels
widthOfSamplesPX = int(np.ceil(widthOfSampleMM*dpmm)) # get the width
widthOfSamplesPX = widthOfSamplesPX + 10 - widthOfSamplesPX % 10 # round up the width to nearest 10
heightOfSamplePX = int(np.ceil(heightOfSampleMM*dpmm)) # get the height
heightOfSamplePX = heightOfSamplePX + 10 - heightOfSamplePX % 10 # round up the height to nearest 10
patternSizePX = patternSizeMM*dpmm # this is the size of the pattern, so far I am going with circles
# init an empty image
im = 255*np.ones((heightOfSamplePX, widthOfSamplesPX), dtype = np.uint8)
# horizontal circle centres
numPoints = int(density*heightOfSamplePX/patternSizePX) # get number of patterns possible
if numPoints==1:
    horizontal = [heightOfSamplePX // 2]
else:
    horizontal = [int(i * heightOfSamplePX / (numPoints + 1)) for i in range(1, numPoints + 1)]
# vertical circle centres
numPoints = int(density*widthOfSamplesPX/patternSizePX)
if numPoints==1:
    vertical = [widthOfSamplesPX // 2]
else:
    vertical = [int(i * widthOfSamplesPX / (numPoints + 1)) for i in range(1, numPoints + 1)]
for i in vertical:
    for j in horizontal:
        # generate the noisy information
        iWithNoise = i+variation*np.random.randint(-2*patternSizePX/density, +2*patternSizePX/density)
        jWithNoise = j+variation*np.random.randint(-2*patternSizePX/density, +2*patternSizePX/density)
        patternSizePXWithNoise = patternSizePX+patternSizePX*variation*(np.random.rand()-0.5)/2
        cv2.circle(im, (int(iWithNoise),int(jWithNoise)), int(patternSizePXWithNoise//2), 0, -1) # add circle

在这一步之后,我可以得到 im ,这是一个低质量的例子 dpi=1000

bad example

这是一个带有我的目标 dpi (5280):

good example

现在我想以可处理的方式以高质量 (DPI>1000) 保存 im 有什么方法可以做到这一点吗?


到目前为止我尝试过的东西:

  1. 使用具有不同 DPI 值的 PNG、TIFF、SVG、PDF 绘制和保存绘图图像 plt.savefig() 使用不同的 dpi
  2. cv2.imwrite() 太文件很大,这里唯一的解决方案是降低 DPI,这也会降低质量
  3. 从矩阵写入 SVG: 我开发了这个功能,但最终文件太大:
import svgwrite
def matrix_to_svg(matrix, filename, padding = 0, cellSize=1):
    # get matrix dimensions and extremes
    rows, cols = matrix.shape
    minVal = np.min(matrix)
    maxVal = np.max(matrix)
    # get a drawing
    dwg = svgwrite.Drawing(filename, profile='tiny', 
                           size = (cols*cellSize+2*padding,rows*cellSize+2*padding))
    # define the colormap, in this case grayscale since black and white
    colorScale = lambda val: svgwrite.utils.rgb(int(255*(val-minVal)/(maxVal-minVal)),
                                                 int(255*(val-minVal)/(maxVal-minVal)),
                                                 int(255*(val-minVal)/(maxVal-minVal)))
    # get the color of each pixel in the matrix and draw it
    for i in range(rows):
        for j in range(cols):
            color = colorScale(matrix[i, j])
            dwg.add(dwg.rect(insert=(j * cellSize + padding, i * cellSize + padding),
                             size=(cellSize, cellSize),
                             fill=color))
    dwg.save() # save
  1. PIL.save() 文件太大

这个问题也可以通过生成更好的形状来解决。这也不会成为障碍。 我愿意使用不同的方法重写,如果有人能指出我正确的方向,我将不胜感激。


生成高分辨率散斑图案并将其保存为合理大小的文件的目标会遇到图像大小和文件大小之间固有的权衡。更高的 DPI(每英寸点数)意味着更多细节但需要更大的文件来存储所有这些信息。以下是一些解决此问题的技巧和策略:

  1. 矢量图形(SVG): 正如所指出的,矢量图形非常适合此任务。它们不像基于像素的格式(如 PNG 或 JPEG)那样存储每个像素的信息,而是以数学方式描述形状。这使它们无论缩放级别如何都能保持清晰度,并且通常具有比其基于像素的对应格式小得多的文件大小。的 matrix_to_svg 函数是一个很好的开始。要进一步减小文件大小,请尝试以下优化:

  2. 简化形状: 如果的圆圈具有重叠,的 SVG 文件当前可能包含多个表示相同重叠区域的形状。可以通过使用布尔运算(如“联合”或“加”)在生成 SVG 之前合并重叠的圆圈来简化这一点。这将减少 SVG 中形状的总数,从而减小文件大小。

  3. 分组形状: 尝试将的圆圈分组为更大的形状。这可以改善 SVG 渲染性能,并可能导致文件大小略有减小。

  4. 实验压缩: 像 SVGO 之样的工具可以使用各种技术(例如删除注释、空格和元数据,以及优化颜色和路径信息)来压缩 SVG 文件。

  5. 有损压缩(JPEG): 如果 SVG 路径不可行,可以探索有损压缩,例如 JPEG,以减小文件大小。JPEG 非常适合于照片和其他具有平滑颜色渐变的图像,但它在处理带有锐利边缘和图案的图像时可能会引入一些伪影。可以尝试不同的 JPEG 质量设置以在文件大小和图像质量之间找到可接受的平衡。

  6. 降低 DPI 要求: 的目标 DPI 为 5280,这对于打印来说非常高。如果的激光雕刻机可以处理,请考虑稍微降低 DPI 要求。即使是 3000 或 2400 DPI 也可以产生高质量的结果,并且可以显着减小文件大小。

  7. 探索替代模式生成方法: 生成散斑图案可能存在计算效率更高的算法或方法。研究不同的算法或库,看看它们是否可以生成具有较小文件大小输出的类似图案。

  8. 程序纹理: 与其生成和存储整个高分辨率图像,不如探索使用程序纹理。在这种方法中,将创建一个小型程序来实时生成散斑图案。此程序将被馈送到的激光雕刻机,以在需要时生成图案,从而无需存储大型文件。

实验并迭代 是找到特定需求的最佳解决方案的关键。尝试不同的技术和设置组合,以在图像质量和文件大小之间找到最佳平衡。

标签:python,opencv,image-processing
From: 78763342

相关文章

  • python入门基础——新手必看
    前言随着人工智能,大数据的发展。python是当前时代最流行,可以在数据处理、web开发、人工智能等多个领域。它的语法简洁、开发效率高、可移植性强,并且可以和其他变成语言(比如C++)轻松衔接,本文主要讲述一些python的变量,基本数据类型,输入、输出,数据类型的转换,运算符等一些必需的......
  • python中逗号运算符的含义
    我理解了python中逗号运算符的简单概念。例如,x0,sigma=0,0.1表示x0=0,sigma=0.1。但我获得了一个代码,其中有一行如下所示。y,xe=np.histogram(np.random.normal(x0,sigma,1000))其中y和xe的输出如下。yOut[10]:array([3,17,58,136,216,25......
  • 【科大讯飞笔试题汇总】2024-07-20-科大讯飞秋招提前批(研发岗)-三语言题解(Cpp/Java/
    ......
  • Python - Pandas - loc vs iloc (DataFrame.loc[:,['column_name':]])
    原文链接:https://blog.csdn.net/weixin_48964486/article/details/123150832————————————————————————————————————————————————关于python数据分析常用库pandas中的DataFrame的loc和iloc取数据基本方法总结归纳及示例如下:1.......
  • 在 Python 中将 2 列的数据框转换为一系列 2 列
    我正在尝试处理一些时间序列数据,并且对pandas数据框相当陌生。我有一个包含两列的数据框,如下所示:+---+-----------------------+-------+--+||0|1||+---+-----------------------+-------+--+|1|2018-08-0223:00:00|456.8||......
  • 基于python的非平稳时间序列模型
    前言平稳时间序列指的是宽平稳时间序列,就是指时间序列的均值、方差和协方差等一二阶矩存在但不随时间改变,表现为时间的常数。若三个条件有一个不成立,那么就称该序列为非平稳时间序列。包括确定性趋势时间序列和随机性趋势时间序列。要想把非平稳的时间序列转化为平稳的时......
  • 猫头虎 Python知识点分享:pandas--read_csv()用法详解
    ......
  • 苦学Opencv的第七天:图像的阈值处理
    PythonOpenCV入门到精通学习日记:图像的阈值处理前言阈值是图像处理中很重要的一个概念,类似于一个标准线。所有像素值都去和这条“标准线”进行比较,会得到大于,小于,等于三种不同的结果,程序对这三种结果进行分组,然后分别对不同组的像素进行“加深”或“变淡”的操作,让整个图......
  • 使用 Python 绘图
    我有一个.txt文件,从中找到有序对,然后使用numpy和matplotlib绘制图形。例如,这些是我的有序对:[[(4.0,0),(0,6.0)],[(6.0,0),(0,3.0)]](每个子列表代表最终图形中的一条线)图形如下所示:但我想找到两条线之间的交点。如果有更多的线,我怎样才能找到它们......
  • 用python计算形状的距离
    我想计算该图像的最小垂直距离和最大水平距离。就像线条一样。我正在尝试:_,binary_image=cv2.threshold(image,0,255,cv2.THRESH_BINARY)horizontal_distances=np.sum(binary_image==255,axis=1)max_horizontal_distance=np.max(horizontal_distance......