[PYTHON] python / PIL로 자동 자르기
PYTHONpython / PIL로 자동 자르기
누구든지 내 이미지 자동 자르기 스크립트에서 무슨 일이 일어나는지 알아낼 수 있습니까? 큰 투명한 영역 / 공간이있는 png 이미지가 있습니다. 그 공간을 자동으로 잘라내어 본질을 남기고 싶습니다. 원래 이미지는 제곱 된 캔버스를 가지고 있으며, 분자를 캡슐화하는 사각형이 최적 인 것이 가장 좋습니다.
여기에 원본 이미지가 있습니다.
일부 인터넷 검색을 사용하면 PIL / Python 코드가 작동한다고보고되었지만 내 손안에는 아래 코드를 실행하면 이미지가 잘려 보입니다.
import Image
import sys
image=Image.open('L_2d.png')
image.load()
imageSize = image.size
imageBox = image.getbbox()
imageComponents = image.split()
rgbImage = Image.new("RGB", imageSize, (0,0,0))
rgbImage.paste(image, mask=imageComponents[3])
croppedBox = rgbImage.getbbox()
print imageBox
print croppedBox
if imageBox != croppedBox:
cropped=image.crop(croppedBox)
print 'L_2d.png:', "Size:", imageSize, "New Size:",croppedBox
cropped.save('L_2d_cropped.png')
출력은 다음과 같습니다.
이미지 처리 / PLI에 익숙한 사람이라면 문제를 파악하는 데 도움이 될까요?
해결법
-
==============================
1.numpy를 사용하여 이미지를 배열로 변환하고 비어 있지 않은 모든 열과 행을 찾아 다음에서 이미지를 만들 수 있습니다.
numpy를 사용하여 이미지를 배열로 변환하고 비어 있지 않은 모든 열과 행을 찾아 다음에서 이미지를 만들 수 있습니다.
import Image import numpy as np image=Image.open('L_2d.png') image.load() image_data = np.asarray(image) image_data_bw = image_data.max(axis=2) non_empty_columns = np.where(image_data_bw.max(axis=0)>0)[0] non_empty_rows = np.where(image_data_bw.max(axis=1)>0)[0] cropBox = (min(non_empty_rows), max(non_empty_rows), min(non_empty_columns), max(non_empty_columns)) image_data_new = image_data[cropBox[0]:cropBox[1]+1, cropBox[2]:cropBox[3]+1 , :] new_image = Image.fromarray(image_data_new) new_image.save('L_2d_cropped.png')
결과는 다음과 같다.
불명확 한 점이 있으면 그냥 물어보십시오.
-
==============================
2.나를 위해 그것이 작동합니다 :
나를 위해 그것이 작동합니다 :
import Image image=Image.open('L_2d.png') imageBox = image.getbbox() cropped=image.crop(imageBox) cropped.save('L_2d_cropped.png')
mask = imageComponents [3]로 경계를 검색하면 파란색 채널 만 검색합니다.
-
==============================
3.나는이 포스트에서 응답 된 응답의 대부분을 시험했다, 그러나, 나는 나의 자신의 응답 높은쪽으로 끝냈다. 나는 anaconda python3을 사용했다.
나는이 포스트에서 응답 된 응답의 대부분을 시험했다, 그러나, 나는 나의 자신의 응답 높은쪽으로 끝냈다. 나는 anaconda python3을 사용했다.
from PIL import Image, ImageChops def trim(im): bg = Image.new(im.mode, im.size, im.getpixel((0,0))) diff = ImageChops.difference(im, bg) diff = ImageChops.add(diff, diff, 2.0, -100) bbox = diff.getbbox() if bbox: return im.crop(bbox) if __name__ == "__main__": bg = Image.open("test.jpg") # The image to be cropped new_im = trim(bg) new_im.show()
-
==============================
4.pyvips를 사용하는 다른 버전이 있습니다.
pyvips를 사용하는 다른 버전이 있습니다.
이것은 약간 애호가입니다. (0, 0)의 픽셀을보고, 배경색으로 가정하고, 중간 값 필터를 수행하고, 더 많은 픽셀과 다른 픽셀을 포함하는 첫 번째와 마지막 행과 열을 찾습니다. 임계 값보다 이 추가 처리는 사진이나 압축 된 이미지에서 작동한다는 것을 의미합니다. 단순한 트림이 노이즈 또는 압축 아티팩트에 의해 제거 될 수 있습니다.
import sys import pyvips # An equivalent of ImageMagick's -trim in libvips ... automatically remove # "boring" image edges. # We use .project to sum the rows and columns of a 0/255 mask image, the first # non-zero row or column is the object edge. We make the mask image with an # amount-differnt-from-background image plus a threshold. im = pyvips.Image.new_from_file(sys.argv[1]) # find the value of the pixel at (0, 0) ... we will search for all pixels # significantly different from this background = im(0, 0) # we need to smooth the image, subtract the background from every pixel, take # the absolute value of the difference, then threshold mask = (im.median(3) - background).abs() > 10 # sum mask rows and columns, then search for the first non-zero sum in each # direction columns, rows = mask.project() # .profile() returns a pair (v-profile, h-profile) left = columns.profile()[1].min() right = columns.width - columns.fliphor().profile()[1].min() top = rows.profile()[0].min() bottom = rows.height - rows.flipver().profile()[0].min() # and now crop the original image im = im.crop(left, top, right - left, bottom - top) im.write_to_file(sys.argv[2])
여기는 8k x 8k 픽셀의 NASA 지구 이미지에서 실행됩니다.
$ time ./trim.py /data/john/pics/city_lights_asia_night_8k.jpg x.jpg real 0m1.868s user 0m13.204s sys 0m0.280s peak memory: 100mb
전에:
후:
여기에 더 많은 토론이있는 블로그 게시물이 있습니다.
-
==============================
5.최근이 게시물을 통해 PIL 라이브러리가 변경되었음을 알게되었습니다. openCV로 다시 구현했습니다.
최근이 게시물을 통해 PIL 라이브러리가 변경되었음을 알게되었습니다. openCV로 다시 구현했습니다.
import cv2 def crop_im(im, padding=0.1): """ Takes cv2 image, im, and padding % as a float, padding, and returns cropped image. """ bw = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) rows, cols = bw.shape non_empty_columns = np.where(bw.min(axis=0)<255)[0] non_empty_rows = np.where(bw.min(axis=1)<255)[0] cropBox = (min(non_empty_rows) * (1 - padding), min(max(non_empty_rows) * (1 + padding), rows), min(non_empty_columns) * (1 - padding), min(max(non_empty_columns) * (1 + padding), cols)) cropped = im[cropBox[0]:cropBox[1]+1, cropBox[2]:cropBox[3]+1 , :] return cropped im = cv2.imread('testimage.png') cropped = crop_im(im) cv2.imshow('', cropped) cv2.waitKey(0)
-
==============================
6.나는이 지위가 낡았다는 것을 알고있다. 그러나 어떤 이유로 든 제안 된 해답 중 아무 것도 나를 위해 일하지 않았다. 그래서 나는 기존 답변에서 내 자신의 버전을 해킹했다.
나는이 지위가 낡았다는 것을 알고있다. 그러나 어떤 이유로 든 제안 된 해답 중 아무 것도 나를 위해 일하지 않았다. 그래서 나는 기존 답변에서 내 자신의 버전을 해킹했다.
import Image import numpy as np import glob import shutil import os grey_tolerance = 0.7 # (0,1) = crop (more,less) f = 'test_image.png' file,ext = os.path.splitext(f) def get_cropped_line(non_empty_elms,tolerance,S): if (sum(non_empty_elms) == 0): cropBox = () else: non_empty_min = non_empty_elms.argmax() non_empty_max = S - non_empty_elms[::-1].argmax()+1 cropBox = (non_empty_min,non_empty_max) return cropBox def get_cropped_area(image_bw,tol): max_val = image_bw.max() tolerance = max_val*tol non_empty_elms = (image_bw<=tolerance).astype(int) S = non_empty_elms.shape # Traverse rows cropBox = [get_cropped_line(non_empty_elms[k,:],tolerance,S[1]) for k in range(0,S[0])] cropBox = filter(None, cropBox) xmin = [k[0] for k in cropBox] xmax = [k[1] for k in cropBox] # Traverse cols cropBox = [get_cropped_line(non_empty_elms[:,k],tolerance,S[0]) for k in range(0,S[1])] cropBox = filter(None, cropBox) ymin = [k[0] for k in cropBox] ymax = [k[1] for k in cropBox] xmin = min(xmin) xmax = max(xmax) ymin = min(ymin) ymax = max(ymax) ymax = ymax-1 # Not sure why this is necessary, but it seems to be. cropBox = (ymin, ymax-ymin, xmin, xmax-xmin) return cropBox def auto_crop(f,ext): image=Image.open(f) image.load() image_data = np.asarray(image) image_data_bw = image_data[:,:,0]+image_data[:,:,1]+image_data[:,:,2] cropBox = get_cropped_area(image_data_bw,grey_tolerance) image_data_new = image_data[cropBox[0]:cropBox[1]+1, cropBox[2]:cropBox[3]+1 , :] new_image = Image.fromarray(image_data_new) f_new = f.replace(ext,'')+'_cropped'+ext new_image.save(f_new)
-
==============================
7.이것은 투명한 배경에서 작동하는 snew의 회신에 비해 개선 된 기능입니다. 수학적 형태학을 사용하면 다음 코드를 사용하여 투명하지 않고 흰색 배경에서 작업 할 수 있습니다.
이것은 투명한 배경에서 작동하는 snew의 회신에 비해 개선 된 기능입니다. 수학적 형태학을 사용하면 다음 코드를 사용하여 투명하지 않고 흰색 배경에서 작업 할 수 있습니다.
from PIL import Image from skimage.io import imread from skimage.morphology import convex_hull_image im = imread('L_2d.jpg') plt.imshow(im) plt.title('input image') plt.show() # create a binary image im1 = 1 - rgb2gray(im) threshold = 0.5 im1[im1 <= threshold] = 0 im1[im1 > threshold] = 1 chull = convex_hull_image(im1) plt.imshow(chull) plt.title('convex hull in the binary image') plt.show() imageBox = Image.fromarray((chull*255).astype(np.uint8)).getbbox() cropped = Image.fromarray(im).crop(imageBox) cropped.save('L_2d_cropped.jpg') plt.imshow(cropped) plt.show()
from https://stackoverflow.com/questions/14211340/automatically-cropping-an-image-with-python-pil by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 아파치 2에서 파이썬 스크립트 실행하기 (0) | 2018.10.24 |
---|---|
[PYTHON] 파이썬에서 ICP (Iterative Closest Point) 구현 (0) | 2018.10.24 |
[PYTHON] Windows에서 파이썬이 사용하는 CA 저장소에 사용자 지정 CA 루트 인증서를 추가하는 방법은 무엇입니까? (0) | 2018.10.24 |
[PYTHON] 어떻게 장고 양식에서 모델 필드를 비활성화 할 수 있습니까? (0) | 2018.10.24 |
[PYTHON] 파이썬 3 - urllib, HTTP 오류 407 : 프록시 인증 필요 (0) | 2018.10.24 |