我面临一个小(大)问题:我想生成高分辨率散斑图案并将其保存为可以导入激光雕刻机的文件。可以是 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
:
这是一个带有我的目标 dpi (5280):
现在我想以可处理的方式以高质量 (DPI>1000) 保存
im
有什么方法可以做到这一点吗?
到目前为止我尝试过的东西:
-
使用具有不同 DPI 值的 PNG、TIFF、SVG、PDF 绘制和保存绘图图像
plt.savefig()
使用不同的 dpi -
cv2.imwrite()
太文件很大,这里唯一的解决方案是降低 DPI,这也会降低质量 - 从矩阵写入 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
-
PIL.save()
文件太大
这个问题也可以通过生成更好的形状来解决。这也不会成为障碍。 我愿意使用不同的方法重写,如果有人能指出我正确的方向,我将不胜感激。
生成高分辨率散斑图案并将其保存为合理大小的文件的目标会遇到图像大小和文件大小之间固有的权衡。更高的 DPI(每英寸点数)意味着更多细节但需要更大的文件来存储所有这些信息。以下是一些解决此问题的技巧和策略:
-
矢量图形(SVG): 正如所指出的,矢量图形非常适合此任务。它们不像基于像素的格式(如 PNG 或 JPEG)那样存储每个像素的信息,而是以数学方式描述形状。这使它们无论缩放级别如何都能保持清晰度,并且通常具有比其基于像素的对应格式小得多的文件大小。的
matrix_to_svg
函数是一个很好的开始。要进一步减小文件大小,请尝试以下优化: -
简化形状: 如果的圆圈具有重叠,的 SVG 文件当前可能包含多个表示相同重叠区域的形状。可以通过使用布尔运算(如“联合”或“加”)在生成 SVG 之前合并重叠的圆圈来简化这一点。这将减少 SVG 中形状的总数,从而减小文件大小。
-
分组形状: 尝试将的圆圈分组为更大的形状。这可以改善 SVG 渲染性能,并可能导致文件大小略有减小。
-
实验压缩: 像 SVGO 之样的工具可以使用各种技术(例如删除注释、空格和元数据,以及优化颜色和路径信息)来压缩 SVG 文件。
-
有损压缩(JPEG): 如果 SVG 路径不可行,可以探索有损压缩,例如 JPEG,以减小文件大小。JPEG 非常适合于照片和其他具有平滑颜色渐变的图像,但它在处理带有锐利边缘和图案的图像时可能会引入一些伪影。可以尝试不同的 JPEG 质量设置以在文件大小和图像质量之间找到可接受的平衡。
-
降低 DPI 要求: 的目标 DPI 为 5280,这对于打印来说非常高。如果的激光雕刻机可以处理,请考虑稍微降低 DPI 要求。即使是 3000 或 2400 DPI 也可以产生高质量的结果,并且可以显着减小文件大小。
-
探索替代模式生成方法: 生成散斑图案可能存在计算效率更高的算法或方法。研究不同的算法或库,看看它们是否可以生成具有较小文件大小输出的类似图案。
-
程序纹理: 与其生成和存储整个高分辨率图像,不如探索使用程序纹理。在这种方法中,将创建一个小型程序来实时生成散斑图案。此程序将被馈送到的激光雕刻机,以在需要时生成图案,从而无需存储大型文件。
实验并迭代 是找到特定需求的最佳解决方案的关键。尝试不同的技术和设置组合,以在图像质量和文件大小之间找到最佳平衡。
标签:python,opencv,image-processing From: 78763342