如何修复Python中图像和情节之间的错位?

发布于 2025-01-30 04:23:52 字数 1089 浏览 2 评论 0原文

我的目标是显示一个二进制图像,然后将边界轮廓绘制为覆盖图像的线。如果我这样做并将结果导出为PDF,则会看到图像和轮廓之间逐渐恶化,因为一个人从左下方移动了整个图像。因此,似乎在背景图像或轮廓的位置存在乘法误差。

我认为问题是由PDF渲染器引起的。如果我以非常高的DPI输出PNG中的结果,我可以删除问题,但是由于其他原因,我更喜欢PDF。有人知道我是否可以更改设置以使PDF正确渲染?

这是一个示例和结果图像。您会看到左下角在图像和轮廓之间具有良好的对齐方式,右上角是最差的。

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

# Make a test image
img = np.zeros((100,100), dtype=np.uint8)
img[20:99,1:80] = 1
img = np.matlib.repmat(img, 9, 6)

# Extract contours
cntrs, hier = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

# Make overlay
fig = plt.figure(figsize=(6,9), dpi=300)
ax = fig.add_subplot()
ax.imshow(img, interpolation='none', cmap=plt.cm.gray)
for cntr in cntrs:
    x = np.append(cntr[:, 0, 0], cntr[0, 0, 0])
    y = np.append(cntr[:, 0, 1], cntr[0, 0, 1])
    ax.plot(x, y, c='r', linewidth=0.5, alpha=0.7)
ax.axis('off')

# Save overlay
plt.savefig('test.pdf', dpi=fig.dpi)

My goal is to show a binary image and then plot the boundary contours as lines overlaying the image. If I do this and export the result as a PDF, I see a progressively worsening misalignment between the image and contours as one moves across the image from bottom left. So it seems like there is a multiplicative error in the position of either the background image or the contours.

I think the issue is caused by the PDF renderer. If I output the result in PNG with a very high DPI, I can remove the problem, but I would prefer PDF for other reasons. Does anyone know if there is a setting I can change to make the PDF render correctly?

Here is an example and the resulting image. You can see that the bottom left corner has good alignment between image and contour and the top right is the worst.

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

# Make a test image
img = np.zeros((100,100), dtype=np.uint8)
img[20:99,1:80] = 1
img = np.matlib.repmat(img, 9, 6)

# Extract contours
cntrs, hier = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

# Make overlay
fig = plt.figure(figsize=(6,9), dpi=300)
ax = fig.add_subplot()
ax.imshow(img, interpolation='none', cmap=plt.cm.gray)
for cntr in cntrs:
    x = np.append(cntr[:, 0, 0], cntr[0, 0, 0])
    y = np.append(cntr[:, 0, 1], cntr[0, 0, 1])
    ax.plot(x, y, c='r', linewidth=0.5, alpha=0.7)
ax.axis('off')

# Save overlay
plt.savefig('test.pdf', dpi=fig.dpi)

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

姐不稀罕 2025-02-06 04:23:52

您可以使用后端而不是默认pdf后端:

plt.savefig('test.pdf', dpi=fig.dpi, backend='pgf')

这给出了正确的pdf与png文件相同:链接到生成的pdf文件

”在此处输入图像说明”


The reason for the mismatch is the different scaling of the image: while the difference of the red line positions between pdf and pgf backends is 2.6 µm maximum (i.e. not visually discernible), the image sizes differ by about 0.3 mm:

pdf:115.358 x 172.861毫米,左下角为20.574/28.575 mm,
PGF:115.057 x 172.606毫米,左下角为20.574 / 28.606毫米。

You can use the pgf backend instead of the default pdf backend:

plt.savefig('test.pdf', dpi=fig.dpi, backend='pgf')

This gives the correct pdf identical to the png file: link to the generated pdf file:

enter image description here


The reason for the mismatch is the different scaling of the image: while the difference of the red line positions between pdf and pgf backends is 2.6 µm maximum (i.e. not visually discernible), the image sizes differ by about 0.3 mm:

pdf: 115.358 x 172.861 mm with bottom left corner at 20.574 / 28.575 mm,
pgf: 115.057 x 172.606 mm with bottom left corner at 20.574 / 28.606 mm.

下雨或天晴 2025-02-06 04:23:52

肮脏的解决方法是炸毁无花果大小。我在脚本开头引入了一个缩放因素。我还将原始线宽提高到0.6,因为它看起来更好。 .pdf看起来很漂亮

import numpy as np
import matplotlib.pyplot as plt
import numpy.matlib
import cv2
scale = 15
# Make a test image
img = np.zeros((100,100), dtype=np.uint8)
img[20:99,1:80] = 1
img = np.matlib.repmat(img, 9, 6)

# Extract contours
cntrs, hier = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

# Make overlay
fig = plt.figure(figsize=(6*scale,9*scale), dpi=300//scale)
ax = fig.add_subplot()
ax.imshow(img, interpolation='none', cmap=plt.cm.gray)
for cntr in cntrs:
    x = np.append(cntr[:, 0, 0], cntr[0, 0, 0])
    y = np.append(cntr[:, 0, 1], cntr[0, 0, 1])
    ax.plot(x, y, c='r', linewidth=0.6*scale, alpha=0.7)
ax.axis('off')

# Save overlay
plt.savefig('test.pdf')

在这里右上角

A dirty workaround would be to blow up the figsize. I introduced a scaling factor for this purpose at the beginning of the script. I also increased the original linewidth to 0.6 because it looked a bit nicer. The .pdf looks pretty nice

import numpy as np
import matplotlib.pyplot as plt
import numpy.matlib
import cv2
scale = 15
# Make a test image
img = np.zeros((100,100), dtype=np.uint8)
img[20:99,1:80] = 1
img = np.matlib.repmat(img, 9, 6)

# Extract contours
cntrs, hier = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

# Make overlay
fig = plt.figure(figsize=(6*scale,9*scale), dpi=300//scale)
ax = fig.add_subplot()
ax.imshow(img, interpolation='none', cmap=plt.cm.gray)
for cntr in cntrs:
    x = np.append(cntr[:, 0, 0], cntr[0, 0, 0])
    y = np.append(cntr[:, 0, 1], cntr[0, 0, 1])
    ax.plot(x, y, c='r', linewidth=0.6*scale, alpha=0.7)
ax.axis('off')

# Save overlay
plt.savefig('test.pdf')

Here the upper right corner

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文