web-dev-qa-db-ja.com

Pythonを使ってOpenCVで画像をトリミングする方法

PILで以前に行ったように、OpenCVを使用して画像をトリミングする方法.

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を使ったと思います。このような場合は、この機能を正しく使用する方法を説明してください。

150
Nolik

とても簡単です。でこぼこのスライスを使用してください。

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

私はこの質問をして、そしてここで別の答えを見つけました: 興味のあるコピー領域

(0,0)をimと呼ばれる画像の左上隅をx方向、左上をy方向とした場合その画像内の長方形領域の左上の頂点として(x1、y1)、右下の頂点として(x2、y2)があります。

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

これは でっかい配列の索引付けとスライスについての総合的なリソースです は画像の一部を切り取るようなことについてもっとあなたに教えることができます。画像はopencv2では派手な配列として格納されます。

:)

94
samkhan13

イメージスライスは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 all only the crops in the memory. 
                                     # im's will be deleted by gc.

これを見つけた後、私は 1つのコメントに気付いた by user1270710 と言っていましたが、見つけるにはかなり時間がかかりました(つまり、デバッグなど)。だから、私はそれが言及する価値があると思います。

7
smttsp

このコードは、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) 
3
m.hatami

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
2
belgraviton

これはもっと堅牢な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
1
Dan Erez

以下は画像をトリミングする方法です。

image_path: 編集する画像へのパス

座標: x/y座標のタプル(x1、y1、x2、y2)

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 __== '__main__':
    image = "image.jpg"
    crop(image, (100, 210, 710,380 ), 'cropped.jpg')
0
Sanyal