PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, July 27, 2022

[FIXED] How to crop the mobile from that image?

 July 27, 2022     crop, opencv, python     No comments   

Issue

I want to crop the mobile from below image:

crop mobile phone

For doing that, I am trying to detect a rectangle shape in the image, and then cropping the image using following code:

import cv2
import numpy as np

img = cv2.imread('rt1.jpg')

imgGry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret , thrash = cv2.threshold(imgGry, 240 , 255, cv2.CHAIN_APPROX_NONE)
contours , hierarchy = cv2.findContours(thrash, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
j=0
for contour in contours:
    approx = cv2.approxPolyDP(contour, 0.01* cv2.arcLength(contour, True), True)
    cv2.drawContours(img, [approx], 0, (0, 0, 0), 5)
    if len(approx) == 4 :
        x, y , w, h = cv2.boundingRect(approx)
        cv2.putText(img, "mobile", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
        out = img[y:y+h,x:x+w]
        cv2.imwrite('cropped'+str(j)+'.jpg', out)
        j = j+1
cv2.imshow('shapes', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

But it is not cropping the mobile phone. Can you suggest any improvement in the code for getting the desired result?


Solution

There's no need to do the approximation on the contours. For that specific image, you'll get one large contour, which you can simply get the bounding rectangle from, and crop the desired part. I optionally added setting the background transparent.

import cv2
import numpy as np

# Read image, convert to grayscale
img = cv2.imread('images/2EZyS.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Threshold image, attention: cv2.THRESH_BINARY_INV!
thr = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)[1]

# Find contours w.r.t. the OpenCV version, attention: cv2.RETR_EXTERNAL!
cnts = cv2.findContours(thr, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

# Filter contours by size
cnts = [cnt for cnt in cnts if cv2.contourArea(cnt) > 2000]
thr = cv2.drawContours(np.zeros_like(thr), cnts, -1, 255, cv2.FILLED)

# Prepare output
out = img.copy()

# Optional: Set background transparent.
out = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
out[..., 3] = thr

# Crop
x, y, w, h = cv2.boundingRect(thr)
out = out[y:y+h, x:x+w]

# Save with and without transparency
cv2.imwrite('crop_w.png', out)
cv2.imwrite('crop_wo.png', out[..., :3])

That'd be the output image with transparency:

Output with transparency

In your original code, you had cv2.CHAIN_APPROX_NONE in the cv2.threshold call. By chance, that value equals 1, which also is cv2.THRESH_BINARY_INV. Nevertheless, you should pay attention to that details.

Also, I'd use cv2.RETR_EXTERNAL instead of cv2.RETR_TREE here, since you only have one object, such that finding the most outer contours is sufficient.

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
NumPy:         1.20.2
OpenCV:        4.5.1
----------------------------------------


Answered By - HansHirse
Answer Checked By - Pedro (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing