पायथन का उपयोग करके ओपनसीवी में एक छवि कैसे क्रॉप करें


233

मैं छवियों को कैसे क्रॉप कर सकता हूं, जैसे मैंने पहले पीआईएल में किया है, ओपनसीवी का उपयोग करके।

जनहित याचिका पर काम करने का उदाहरण

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। यदि यह मामला है, तो कृपया बताएं कि मैं इस फ़ंक्शन का सही उपयोग कैसे कर सकता हूं।

जवाबों:


527

यह बहुत सरल है। सुन्न स्लाइसिंग का उपयोग करें।

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

9
हम्म ... लेकिन मैं फसल छवि को चर में कैसे बचा सकता हूं?
नोलिक

56
याद रखें कि x और y फ़्लिप हैं। मुझसे यह छूट गया।
अंकसूची 26:18

10
वैकल्पिक रूप से, यदि आपने फसल मार्जिन को परिभाषित किया है, तो आप कर सकते हैंcrop_img = img[margin:-margin, margin:-margin]
Rufus

39
यह बहुत अच्छा है, बस इस बात से अवगत रहें कि फसल बदलने से_मग बदल जाएगा। अन्यथा, आपको फसल_मग = इमग [y: y + h, x: x + w] .copy ()
user1270710

1
@javadba सुन्न कार्यान्वयन विस्तार। Numpy पंक्ति, पंक्ति संकेतन का उपयोग करता है बजाए, पंक्ति
Froyo

121

मेरे पास यह सवाल था और मुझे एक और जवाब मिला: ब्याज की प्रतिलिपि क्षेत्र

यदि हम (0,0) को छवि के शीर्ष बाएं कोने के imरूप में x दिशा के रूप में बाएँ-से-दाएँ और y- दिशा के रूप में शीर्ष-से-नीचे के रूप में मानते हैं। और हमारे पास (X1, y1) शीर्ष-बाएँ शीर्ष के रूप में और (x2, y2) उस छवि के भीतर एक आयत क्षेत्र के निचले-दाएँ शीर्ष के रूप में, फिर:

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

यहां पर एक व्यापक संसाधन है numpy सरणी अनुक्रमण और टुकड़ा करने की क्रिया है जो आप एक छवि का एक हिस्सा फसल जैसी चीजों के बारे में अधिक बता सकते हैं। छवियों को opencv2 में एक सुव्यवस्थित सरणी के रूप में संग्रहीत किया जाएगा।

:)


नमस्ते, यह नहीं होना चाहिए `रोटी = im [y1: y2 + 1, X1: x2 + 1]` आप परिस्थितियों में? क्योंकि खस्ता करने के लिए सुन्न क्षेत्र को बाहर रखा गया है।
स्कॉट यांग

@ samkhan13, जब मैं इस फॉर्मूले का उपयोग करके फसल करता हूं, तो मेरी सभी फसलों का आकार (0, चौड़ाई, चैनल) होता है। अर्थात। मुझे ay आयाम बिल्कुल नहीं मिल रहा है
mLstudent33

@ mLstudent33 यह संभावना है कि छवि imको सही ढंग से पढ़ा नहीं गया है और खाली है। अपने कोड चरण का निदान करने के लिए ब्रेकपॉइंट्स के साथ IDE का उपयोग करने का प्रयास करें। आप कोड ब्लॉक बनाने के लिए Google कोलाब का उपयोग कर सकते हैं और किसी की मदद लेने के लिए स्टैकओवरफ्लो अजगर चैट रूम पर अपने ज्यूपिटोर नोटबुक को साझा कर सकते हैं।
samkhan13

@ samkhan13 वास्तव में मेरे पास एक अजीब मुद्दा है जिसे मैंने गितुब ओपेनकेव मुद्दों पर पोस्ट किया है: github.com/opencv/opencv/issues/15406 मैं चैट भी देखूंगा । धन्यवाद!
mLstudent33

16

ध्यान दें कि, इमेज स्लाइसिंग कॉपी नहीं बना रहा है, cropped imageलेकिन एक pointerसे बना रहा है roi। यदि आप इतने सारे चित्रों को लोड कर रहे हैं, स्लाइसिंग के साथ छवियों के प्रासंगिक भागों को क्रॉप कर रहे हैं, तो एक सूची में संलग्न करना, यह एक विशाल मेमोरी बेकार हो सकता है।

मान लीजिए कि आप प्रत्येक चित्र को एन लोड करते हैं >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.

यह पता लगाने के बाद, मुझे उपयोगकर्ता 1212710 द्वारा टिप्पणियों में से एक का उल्लेख किया गया था, लेकिन इसका पता लगाने में मुझे काफी समय लगा (यानी, डिबगिंग आदि)। इसलिए, मुझे लगता है कि यह उल्लेख के लायक है।


इस पर एक नज़र डालें: stackoverflow.com/q/60359398/7644562
अब्दुल रहमान

कब्जे में स्मृति स्थान के संबंध में, मैं समझता हूं कि ब्याज के क्षेत्र की नकल करना सबसे अच्छी बात है, लेकिन समय लेने के बारे में क्या? यदि मैं copy()टुकड़ा करने की तुलना में आरओआई करता हूं , तो परिणाम क्या होगा? इसके अलावा, अगर मेरे पास एक चर tmpहै जिसमें मैं अपने कंप्यूटर से लोड की गई प्रत्येक तस्वीर को संग्रहीत करता हूं, तो स्लाइसिंग का मेरी मेमोरी पर बुरा प्रभाव नहीं होना चाहिए, है ना? आपके द्वारा वर्णित समस्या केवल उस चीज से संबंधित है जब आप सभी छवियों को लोड करते हैं और फिर आप उन्हें आरओआई स्टोर करते हैं, जिसमें दोनों मूल और आरओआई होते हैंकृपया मुझे बताएं कि क्या मैंने सही समझा।
सायला सिलिना

मेरे द्वारा कहे गए मामले में नकल करना नगण्य समय होगा। जब तक आप बड़ी छवियों को कई बार कॉपी नहीं करते, तब तक आपके पास समय का अंतर नहीं होगा। मेरे कोड में, प्रभाव क्रॉपिंग के प्रति 1ms से कम की तरह होगा। समस्या यह है कि आप या तो बड़ी छवि और एक पॉइंटर (ROI जो केवल कुछ बाइट्स हैं) को स्टोर करते हैं या आप मेमोरी में एक छोटी सी छवि (मेरे मामले में) स्टोर करते हैं। यदि आप कुछ समय ऐसा करते हैं, तो यह ठीक है। हालाँकि यदि आप ऐसा हज़ारों बार करते हैं, तो मेमोरी उपयोग स्लाइसिंग के साथ पागल हो जाएगा। जैसे आप एक जोड़ी के बाद पूरी मेमोरी भरते हैं अगर हजार इमेज लोडिंग करते हैं अगर आप स्लाइसिंग करते हैं। जबकि मेरा कोड अभी भी आदेश पर होगा यदि MB
smttsp

12

यह कोड 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) 

@ शमी, इतनी ऊँचाई १०० पिक्सेल "नीचे" y = ० सही है? यह सुपीरियर सरणी की 101 वीं पंक्ति है? और चौड़ाई x = 0 सही के दाईं ओर 200 पिक्सेल है?
mLstudent33

4

नीचे एक छवि को क्रॉप करने का तरीका है।

image_path: संपादित करने के लिए छवि का पथ

coord: x / y निर्देशांक (X1, y1, x2, y2) की एक गुच्छी [mspaint में छवि खोलें और निर्देशांक देखने के लिए दृश्य टैब में "शासक" की जाँच करें]

save_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')

3

ओपेकव कॉपी बॉर्डर फ़ंक्शन के साथ मजबूत फसल:

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

क्या आप कृपया बता सकते हैं कि यहाँ क्या है और हम इसके मूल्य में क्या देना चाहते हैं क्योंकि मैं जो भी मानने की कोशिश कर रहा हूँ, वह मुझे यह x1,y1,x2,y2 = bbox कहते हुए त्रुटि दे रहा है:TypeError: 'int' object is not iterable
सबा

3

यहाँ अधिक मजबूत 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

वैकल्पिक रूप से, आप छवि से एक सरणी बनाने के लिए क्रॉपिंग और ओपनसीवी के लिए टेंसरफ़्लो का उपयोग कर सकते हैं।

import cv2
img = cv2.imread('YOURIMAGE.png')

अब imgएक (छवि, छवि, 3) आकार सरणी है। दहाई के साथ सरणी को काटें:

import tensorflow as tf
offset_height=0
offset_width=0
target_height=500
target_width=500
x = tf.image.crop_to_bounding_box(
    img, offset_height, offset_width, target_height, target_width
)

छवि को tf.keras के साथ फिर से इकट्ठा करें, इसलिए हम इसे देख सकते हैं यदि यह काम किया है:

tf.keras.preprocessing.image.array_to_img(
    x, data_format=None, scale=True, dtype=None
)

यह एक नोटबुक में तस्वीर को प्रिंट करता है (Google Colab में परीक्षण किया गया)।


पूरा कोड एक साथ:

import cv2
img = cv2.imread('YOURIMAGE.png')

import tensorflow as tf
offset_height=0
offset_width=0
target_height=500
target_width=500
x = tf.image.crop_to_bounding_box(
    img, offset_height, offset_width, target_height, target_width
)

tf.keras.preprocessing.image.array_to_img(
    x, data_format=None, scale=True, dtype=None
)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.