web-dev-qa-db-fra.com

Comment recadrer une image dans OpenCV en utilisant Python

Comment puis-je recadrer des images, comme je l’ai déjà fait dans PIL, avec OpenCV?.

Exemple de travail sur PIL

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

Mais comment puis-je le faire sur OpenCV?

C'est ce que j'ai essayé:

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)

Mais ça ne marche pas.

Je pense avoir mal utilisé getRectSubPix. Si tel est le cas, veuillez expliquer comment utiliser correctement cette fonction.

168
Nolik

C'est très simple. Utilisez numpy slicing.

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

j'ai eu cette question et a trouvé une autre réponse ici: copie région d'intérêt

Si nous considérons (0,0) comme coin supérieur gauche de l’image appelée im, avec de gauche à droite la direction x et de haut en bas la direction y. et nous avons (x1, y1) comme sommet en haut à gauche et (x2, y2) en tant que sommet en bas à droite d'une région rectangle dans cette image, puis:

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

voici une ressource complète sur numpy array indexing and slicing qui peut vous en dire plus sur des choses telles que le rognage d'une partie d'une image. les images seraient stockées sous forme de tableau numpy dans opencv2.

:)

102
samkhan13

Notez que le découpage d’image ne crée pas une copie du cropped image mais crée un pointer sur le roi. Si vous chargez autant d'images, en coupant les parties pertinentes avec des découpes, puis en les ajoutant à une liste, vous risquez de perdre énormément de mémoire.

Supposons que vous chargez N images chacune étant >1MP et que vous n’ayez besoin que de la région 100x100 à partir du coin supérieur gauche.

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.

Vous pouvez également copier la pièce correspondante de .copy(), de sorte que Garbage Collector supprimera 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.

Après avoir découvert cela, je compris n des commentaires par ser127071 mentionné, mais il me fallut un certain temps pour le savoir (débogage, etc.). Donc, je pense que cela mérite d'être mentionné.

11
smttsp

ce code recadrer une image de x = 0, y = 0 position à 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) 
4
m.hatami
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')

image_path: Le chemin de l'image à éditer

coords: Un tuple de coordonnées x/y (x1, y1, x2, y2) [ouvrez l'image dans mspaint et vérifiez la "règle" dans l'onglet de vue pour voir les coordonnées]

Saved_location: chemin pour enregistrer l'image recadrée

3
Sanyal

voici du code pour une imcrop plus robuste (un peu comme dans 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
2
Dan Erez

Recadrage robuste avec fonction de copie ouverte:

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