Python PIL-透明和虚线?

Python PIL-透明和虚线?,python,python-imaging-library,Python,Python Imaging Library,我试图在图像上叠加一个网格,这样我就可以用它来定位文本。我正在使用PIL(Python)绘制网格。理想情况下,我会有虚线和合理透明的次要网格线,这样我就可以看穿图像,以及实心和不太透明的主要网格线 下面是我正在尝试做的一个工作示例 我的问题涉及以下几行(简化为演示): 1) 我知道填充的第四个参数控制线条的透明度,0表示完全透明,255表示完全不透明。但是,我无法检测值或1或200之间的任何差异,事实上,当我使用1时,当我认为可以看到它时,它会隐藏它下面的文本 2) 如何在PIL中绘制虚线?我不

我试图在图像上叠加一个网格,这样我就可以用它来定位文本。我正在使用PIL(Python)绘制网格。理想情况下,我会有虚线和合理透明的次要网格线,这样我就可以看穿图像,以及实心和不太透明的主要网格线

下面是我正在尝试做的一个工作示例

我的问题涉及以下几行(简化为演示):

1) 我知道填充的第四个参数控制线条的透明度,0表示完全透明,255表示完全不透明。但是,我无法检测值或1或200之间的任何差异,事实上,当我使用1时,当我认为可以看到它时,它会隐藏它下面的文本

2) 如何在PIL中绘制虚线?我不知道怎么做。可能吗

最后,我对编程和python比较陌生,如果您能在下面的MWE中提供一些技巧,使其达到更好的标准,我将不胜感激

注意:下面的示例使用红线作为主要网格线,但我希望它们与次要网格线的颜色相同,次要网格线透明且为虚线

import PIL
from PIL import Image, ImageFont, ImageDraw

grid = 'on'
minor = 5
major = 50

font = ImageFont.truetype('arial.ttf', 10)
textColor = (38, 23, 255)

img = Image.open('2013MCS7.jpg')
draw = ImageDraw.Draw(img)


def gridlines(img, gridWidth, color, lineWidth=1, direction='b', label='n', labelRepeat=None, LabelFont='arial', labelFontSize=10):
    '''
    Draws gridlines on an image.
        img : the image to be modified
        gridwith : (int > 0) : size of gridlines in pixels
        color : tuple of length 3 or 4 (4th argument controls transparency) : color of gridlines and labels
        lineWidth : (int > 0) : width of gridlines
        direction : ('v','h','b') : specifies either vetical gridlines, horizontal gridlines or both
        label : ('y','n') : turns grid labels on or off
        labelRepeat : 
    '''
    imgWidth, imgHeight = img.size
    draw = ImageDraw.Draw(img)
    textColor = (color[0], color[1], color[2])
    textFont = ImageFont.truetype(LabelFont+'.ttf', labelFontSize) 

    # add gridlines
    if direction.lower() == 'b' or direction.lower() == 'v':
        for v in range(1, int(imgWidth/gridWidth)+1):
            draw.line( (v*gridWidth, 0, v*gridWidth, imgHeight), fill = color, width = lineWidth )

    if direction.lower() == 'b' or direction.lower() == 'h':
        for h in range(1, int(imgHeight/gridWidth)+1):
            draw.line( (0, h*gridWidth, imgWidth, h*gridWidth), fill = color, width = lineWidth )

    # add labels
    if label.lower() == 'y':
        for v in range(1, int(imgWidth/gridWidth)+1):
            for h in range(1, int(imgHeight/gridWidth)+1):
                if v == 1:
                    draw.text( ( 3, 1+h*gridWidth), str(h), fill = textColor, font = textFont )
                if h == 1:
                    draw.text( ( 1+v*gridWidth, 3), str(v), fill = textColor, font = textFont )
                if labelRepeat is not None:
                    if ( h % labelRepeat == 0 ) and ( v % labelRepeat == 0 ): 
                        draw.text( ( 1+v*gridWidth, 1+h*gridWidth), '('+str(h)+','+str(v)+')', fill = textColor, font = textFont )



# draw gridlines

if grid == 'on':
    gridlines(img, minor, (180, 180, 255,   1))
    gridlines(img, major, (255,   0,   0, 100), label='Y', labelRepeat=3)

# populate form

draw.text( (6*major+2*minor+3, 6*major+5*minor+2), 'econ_total', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 7*major+1*minor+2), 'notional_taxed', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 7*major+7*minor+2), 'notional_employer', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 8*major+4*minor+3), 'supca_total', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 9*major+2*minor-1), 'cgt_exempt_sb_ret', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 9*major+7*minor+0), 'cgt_exempt_sb_15yr', fill=textColor, font=font)


del draw
img.save('marked-up - 2013MCS7.jpg')

首先,用布尔值替换
grid='on'
。您应该使用
True
False
,而不是字符串比较来检查设置是否通过
启用,如果网格:

其次,默认情况下,PIL不能绘制虚线。要画一条虚线,你必须画几条彼此间隔的小线。然而,对于您试图做的事情,虚线应该是不必要的;可以通过高度控制来设置线条的不透明度

最后,您应该能够通过您的方法对线条的不透明度进行非常精细的控制。
gridlines()
函数正在做大量额外的工作;它会无缘无故地重新绘制图像、绘制文本等。因此,最可能发生的情况是网格线被绘制了多次,导致它们变得越来越不透明


如果您的网格绘制正常,则应将图像保存为PNG,而不是JPEG。JPEG不能很好地渲染红色,因为它是为了保存照片图像而设计的,这意味着它将更多的信息用于存储绿色和蓝色,而我们的眼睛可以看到更多的绿色和蓝色。

谢谢。我将用真/假替换开/关,并按照您的建议以PNG格式保存。2个简短的问题。(1) 当您说“它无缘无故地重画图像”时,您是指函数中的语句“draw=ImageDraw.draw(img)”,还是它也发生在其他地方(我不知道)?我把它放在函数中,使它成为独立的,而不必通过draw,但我将返工。(2) 我不明白‘所以最可能发生的是你们的网格线被画了好几次’。我看不出这是怎么发生的。你能详细说明一下吗?如果这个问题解决了你的问题,别忘了把它标记为正确。根据上面的评论,它并没有真正解决我的问题。我无法使透明度发挥作用(对我来说仍然是不透明的),我也看不到我的代码是如何导致网格线彼此绘制多次的(for循环以不同的间隔绘制网格线)。我已经去掉了第二个对“draw=ImageDraw.draw(img)”的引用,因为我假设这就是“它无缘无故地重新绘制图像”的意思,但我最初这样做是为了使函数自包含,而不通过参数draw,因为我认为这样会更好,但我不确定这两次绘制的成本。
import PIL
from PIL import Image, ImageFont, ImageDraw

grid = 'on'
minor = 5
major = 50

font = ImageFont.truetype('arial.ttf', 10)
textColor = (38, 23, 255)

img = Image.open('2013MCS7.jpg')
draw = ImageDraw.Draw(img)


def gridlines(img, gridWidth, color, lineWidth=1, direction='b', label='n', labelRepeat=None, LabelFont='arial', labelFontSize=10):
    '''
    Draws gridlines on an image.
        img : the image to be modified
        gridwith : (int > 0) : size of gridlines in pixels
        color : tuple of length 3 or 4 (4th argument controls transparency) : color of gridlines and labels
        lineWidth : (int > 0) : width of gridlines
        direction : ('v','h','b') : specifies either vetical gridlines, horizontal gridlines or both
        label : ('y','n') : turns grid labels on or off
        labelRepeat : 
    '''
    imgWidth, imgHeight = img.size
    draw = ImageDraw.Draw(img)
    textColor = (color[0], color[1], color[2])
    textFont = ImageFont.truetype(LabelFont+'.ttf', labelFontSize) 

    # add gridlines
    if direction.lower() == 'b' or direction.lower() == 'v':
        for v in range(1, int(imgWidth/gridWidth)+1):
            draw.line( (v*gridWidth, 0, v*gridWidth, imgHeight), fill = color, width = lineWidth )

    if direction.lower() == 'b' or direction.lower() == 'h':
        for h in range(1, int(imgHeight/gridWidth)+1):
            draw.line( (0, h*gridWidth, imgWidth, h*gridWidth), fill = color, width = lineWidth )

    # add labels
    if label.lower() == 'y':
        for v in range(1, int(imgWidth/gridWidth)+1):
            for h in range(1, int(imgHeight/gridWidth)+1):
                if v == 1:
                    draw.text( ( 3, 1+h*gridWidth), str(h), fill = textColor, font = textFont )
                if h == 1:
                    draw.text( ( 1+v*gridWidth, 3), str(v), fill = textColor, font = textFont )
                if labelRepeat is not None:
                    if ( h % labelRepeat == 0 ) and ( v % labelRepeat == 0 ): 
                        draw.text( ( 1+v*gridWidth, 1+h*gridWidth), '('+str(h)+','+str(v)+')', fill = textColor, font = textFont )



# draw gridlines

if grid == 'on':
    gridlines(img, minor, (180, 180, 255,   1))
    gridlines(img, major, (255,   0,   0, 100), label='Y', labelRepeat=3)

# populate form

draw.text( (6*major+2*minor+3, 6*major+5*minor+2), 'econ_total', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 7*major+1*minor+2), 'notional_taxed', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 7*major+7*minor+2), 'notional_employer', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 8*major+4*minor+3), 'supca_total', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 9*major+2*minor-1), 'cgt_exempt_sb_ret', fill=textColor, font=font)
draw.text( (6*major+2*minor+3, 9*major+7*minor+0), 'cgt_exempt_sb_15yr', fill=textColor, font=font)


del draw
img.save('marked-up - 2013MCS7.jpg')