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