[python] Python을 사용하여 OpenCV에서 이미지를 자르는 방법

OpenCV를 사용하여 이전에 PIL에서 한 것처럼 이미지를 자르는 방법

PIL의 실례

im = Image.open('0.png').convert('L')
im = im.crop((1, 1, 98, 33))
im.save('_0.png')

그러나 OpenCV에서 어떻게 할 수 있습니까?

이것이 내가 시도한 것입니다.

im = cv.imread('0.png', cv.CV_LOAD_IMAGE_GRAYSCALE)
(thresh, im_bw) = cv.threshold(im, 128, 255, cv.THRESH_OTSU)
im = cv.getRectSubPix(im_bw, (98, 33), (1, 1))
cv.imshow('Img', im)
cv.waitKey(0)

그러나 작동하지 않습니다.

내가 잘못 사용했다고 생각 getRectSubPix합니다. 이 경우이 기능을 올바르게 사용하는 방법을 설명하십시오.



답변

매우 간단합니다. numpy 슬라이싱을 사용하십시오.

import cv2
img = cv2.imread("lenna.png")
crop_img = img[y:y+h, x:x+w]
cv2.imshow("cropped", crop_img)
cv2.waitKey(0)


답변

나는이 질문을했고 여기에 다른 대답을 찾았습니다. 관심있는 복사 영역

(0,0)을 이미지의 왼쪽 상단으로 간주하면 im왼쪽에서 오른쪽으로 x 방향으로, 위에서 아래로 y 방향으로 호출 됩니다. 그리고 우리는 (x1, y1)을 왼쪽 위 꼭지점으로하고 (x2, y2)를 그 이미지 내 사각형 영역의 오른쪽 아래 꼭지점으로합니다.

roi = im[y1:y2, x1:x2]

다음은 이미지의 일부를 자르는 것과 같은 것들에 대해 더 많이 알 수있는 numpy 배열 인덱싱 및 슬라이싱 에 대한 포괄적 인 리소스입니다 . 이미지는 opencv2에 numpy 배열로 저장됩니다.

🙂


답변

이미지 슬라이스가의 사본을 생성하지 않는, 그 주 cropped image만 생성 pointer받는 사람을 roi. 너무 많은 이미지를로드하고 슬라이싱을 사용하여 이미지의 관련 부분을 자르고 목록에 추가하면 메모리 낭비가 커질 수 있습니다.

N 개의 이미지를 각각로드 >1MP하고 100x100왼쪽 상단에서 영역 만 필요하다고 가정합니다 .

Slicing:

X = []
for i in range(N):
    im = imread('image_i')
    X.append(im[0:100,0:100]) # This will keep all N images in the memory. 
                              # Because they are still used.

또는으로 관련 부분을 복사 할 수 .copy()있으므로 가비지 수집기가 제거 im합니다.

X = []
for i in range(N):
    im = imread('image_i')
    X.append(im[0:100,0:100].copy()) # This will keep only the crops in the memory. 
                                     # im's will be deleted by gc.

이를 찾는 후, 나는 깨달았다 의견 중 하나 에 의해 user1270710 언급을하지만 (즉, 디버깅 등)를 찾아 나에게 꽤 시간이 걸렸습니다. 따라서 언급 할 가치가 있다고 생각합니다.


답변

이 코드는 x = 0, y = 0 위치에서 h = 100, w = 200으로 이미지 자르기

import numpy as np
import cv2

image = cv2.imread('download.jpg')
y=0
x=0
h=100
w=200
crop = image[y:y+h, x:x+w]
cv2.imshow('Image', crop)
cv2.waitKey(0) 


답변

아래는 이미지를 자르는 방법입니다.

image_path : 편집 할 이미지의 경로

coords : x / y 좌표의 튜플 (x1, y1, x2, y2) [mspaint에서 이미지를 열고 좌표를 보려면보기 탭에서 “ruler”를 확인하십시오.]

saved_location : 자른 이미지를 저장하는 경로

from PIL import Image
    def crop(image_path, coords, saved_location:
        image_obj = Image.open("Path of the image to be cropped")
            cropped_image = image_obj.crop(coords)
            cropped_image.save(saved_location)
            cropped_image.show()


if __name__ == '__main__':
    image = "image.jpg"
    crop(image, (100, 210, 710,380 ), 'cropped.jpg')


답변

opencv 복사 테두리 기능이있는 강력한 자르기 :

def imcrop(img, bbox):
   x1, y1, x2, y2 = bbox
   if x1 < 0 or y1 < 0 or x2 > img.shape[1] or y2 > img.shape[0]:
        img, x1, x2, y1, y2 = pad_img_to_fit_bbox(img, x1, x2, y1, y2)
   return img[y1:y2, x1:x2, :]

def pad_img_to_fit_bbox(img, x1, x2, y1, y2):
    img = cv2.copyMakeBorder(img, - min(0, y1), max(y2 - img.shape[0], 0),
                            -min(0, x1), max(x2 - img.shape[1], 0),cv2.BORDER_REPLICATE)
   y2 += -min(0, y1)
   y1 += -min(0, y1)
   x2 += -min(0, x1)
   x1 += -min(0, x1)
   return img, x1, x2, y1, y2


답변

다음은 좀 더 강력한 imcrop에 대한 코드입니다 (matlab과 약간 비슷 함)

def imcrop(img, bbox):
    x1,y1,x2,y2 = bbox
    if x1 < 0 or y1 < 0 or x2 > img.shape[1] or y2 > img.shape[0]:
        img, x1, x2, y1, y2 = pad_img_to_fit_bbox(img, x1, x2, y1, y2)
    return img[y1:y2, x1:x2, :]

def pad_img_to_fit_bbox(img, x1, x2, y1, y2):
    img = np.pad(img, ((np.abs(np.minimum(0, y1)), np.maximum(y2 - img.shape[0], 0)),
               (np.abs(np.minimum(0, x1)), np.maximum(x2 - img.shape[1], 0)), (0,0)), mode="constant")
    y1 += np.abs(np.minimum(0, y1))
    y2 += np.abs(np.minimum(0, y1))
    x1 += np.abs(np.minimum(0, x1))
    x2 += np.abs(np.minimum(0, x1))
    return img, x1, x2, y1, y2