2012-08-29 36 views
2

我必须用python使用PIL裁剪照片。
如果照片区域不够,则该区域的其余部分会涂成黑色。
如何使该区域变白?裁剪图像,改变黑色区域,如果没有足够的照片区域在白色

这是现在使用的代码我真的的一部分:

i = Image.open(filepath) 
box2 = (newX,newY,newX+newW,newY+newH) 
i2=i.crop(box=box2) 
i2.load() 
... 
i2.save(new_filepath) 
... 
white=(255,255,255) 
i3 = Image.new('RGB' , i2.size , white) 
i3.paste(i2) 
i3.save(filepath2,'PNG') 

作物正常工作,但我想白色而不是黑色在该地区的其余部分。 我试图创建一个带有白色背景的新图片并粘贴了图片,但它没有工作。

编辑: 例如输出

example output

EDIT2:我原始图像和用于croping
我更新了代码
Remeber该作物COORDS可以是负的COORDS。

输入&输出例如
输入IMG:http://i.imgur.com/vbmPy.jpg

box2=(-743, 803, 1646, 4307) 

输出IMG:http://i.imgur.com/K7sil.jpg

回答

1

如果你可以使用numpy的,你可以这样做:

i22 = flipud(asarray(i2).copy()) 
# calculate the area that its black, using the original size and the box information 
for i in xrange(blackrows): 
    i22[i:] = asarray([255,255,255]) 
# and and something like that to the blackcolumns 

我不不会使用PIL,但它可能具有一些像素处理功能。

+0

如果图像已经是纯黑色的是什么?这在这种情况下不起作用 – Revelation

0

要完全按照您的要求进行操作,请将图像转换为numpy数组,然后过滤全黑行和列(在第二个图像上)。您不能简单地将所有黑色像素设为白色,因为这会影响图像内部的那些像素。

import numpy 
from PIL import Image 
img = Image.open("hHncu.png") # Imgur's naming scheme 
pix = numpy.array(img)  # Convert to array 

black = numpy.array([0,0,0,255]) 
white = numpy.array([255,255,255,255]) 

pix2 = pix.copy() 
dim = pix.shape 

for n in xrange(dim[0]): 
    if (pix[n,:]==black).all(): 
     pix2[n,:,numpy.newaxis] = white 

for n in xrange(dim[1]): 
    if (pix[:,n]==black).all(): 
     pix2[:,n,numpy.newaxis] = white 

# View the results 
from pylab import * 
subplot(121); imshow(pix) 
subplot(122); imshow(pix2) 
show() 

enter image description here

它看起来像有黑色和图像之间的一些平滑,将需要更先进的过滤器来解决这个问题 - 但你可以看到如何从这里开始!

+0

如果我在黑色区域画白色矩形会怎么样?数组操作听起来有点过度。这是一个网络应用程序,因此加快它的一个重要因素。 – Revelation

+0

你当然可以这样做,但是numpy是数组操作的_designed_,它们闪电般快,所以我不认为这是一个问题。 – Hooked

+0

如果图像已经是纯黑色,该怎么办?这在这种情况下不起作用。 – Revelation

1

它在我看来像你做错了什么,你应该分享你的整个代码和图像。

我已经在PIL中做过这么多次了,最简单的解决方案一直是将作物粘贴到全白图像上。

import Image 

# open source 
i = Image.open('hHncu.png') 

# crop it 
(newX , newY) = (110 , 0) 
(newW , newH) = (110 , 150) 
box_crop = (newX,newY,newX+newW,newY+newH) 
i2 = i.crop(box=box_crop) 
i2.load() 

# save it , just for testing 
i2.save('hHncu-out.png') 

# create the new image, and paste it in 
# note that we're making it 300x300 and have the background set to white (255x3) 
i3 = Image.new('RGB' , (300,300) , (255,255,255)) 
# paste it at an offset. if you put no offset or a box, i3 must match i2s dimensions 
i3.paste(i2 , (25,25)) 
# save it 
i3.save('hHncu-out-2.png') 
+0

我先试过这个解决方案。我用这个解决方案更新了代码,但没有运气。我认为这是因为在裁剪之后,图像已经有了黑色区域,并且我们将其复制/粘贴到新图像上,并将其复制到黑色区域。我输入和输出文件。 – Revelation

+0

上述代码按原样运行。你可能在你的代码中做错了。 发布导致错误的代码的工作示例,以便人们可以更正您的错误。 –

+0

当裁剪区域超出照片区域时,上述代码不起作用。用这个坐标测试你的代码:#裁剪它 '(newX,newY)=(-100,-100) (newW,newH)=(400,250)'你会看到结果 – Revelation

0

好的。所以这里是我提到的想法的快速刺入。

的REBOX()函数返回一个“固定”的边界框,以及一些偏移数据

这部作品在大多数情况下。我没有整合偏移量数据,但它的一些版本可能会在i3.paste部分。

测试图像,grid.png为300x300,蓝色线条为50px,红色线条为150px,绿色线条为200px。

你应该能够根据你的确切需求调整它。

enter image description here

import Image 
i1 = Image.open('grid.png') 


DEBUG = True 

def rebox(box_original , box_crop_desired): 

    box_crop_new= list(box_crop_desired) 
    box_crop_offset = [ 0 , 0 ] 

    if box_crop_desired[0] < 0: 
     box_crop_new[0] = 0 
     box_crop_offset[0] = box_crop_desired[0] 

    if box_crop_desired[1] < 0: 
     box_crop_new[1] = 0 
     box_crop_offset[1] = box_crop_desired[1] 

    if box_crop_desired[2] > box_original[2]: 
     box_crop_new[2] = box_original[2] 

    if box_crop_desired[3] > box_original[3]: 
     box_crop_new[3] = box_original[3] 

    box_crop_offset = tuple(box_crop_offset) 
    box_crop_new = tuple(box_crop_new) 

    if DEBUG : 
     print "box_original      %s" % str(box_original) 
     print "box_crop_offset     %s" % str(box_crop_offset) 
     print "box_crop_desired     %s" % str(box_crop_desired) 
     print "box_crop_new      %s" % str(box_crop_new) 

    return (box_crop_new , box_crop_offset) 


(newX , newY) = (200 , 200) 
(newW , newH) = (400 , 400) 
box_crop_desired = (newX , newY , newX+newW, newY+newH) 
(box_crop , box_crop_offset) = rebox(i1.getbbox() , box_crop_desired) 

i2 = i1.crop(box=box_crop) 
i2.save('grid-out-b.png') 

i3 = Image.new('RGBA' , (newW , newH) , (255,255,255)) 
i3.paste(i2 , (0,0)) 
i3.save('grid-out-final-b.png')