5

I want to crop images automatically.

I am using ImageMagick for this .

Command i am using

 convert  3.jpg  -fuzz 10%  -trim     trim.jpg

enter image description here

enter image description here

How do i fix this .

I think there is problem with fuzz factor which am setting .

usernan
  • 572
  • 1
  • 6
  • 23
  • You probably need to pay more attention to using a contrasting background when you shoot your photos in the first place - like when videographers do chroma keying... https://en.wikipedia.org/wiki/Chroma_key – Mark Setchell Jun 14 '16 at 10:14
  • @MarkSetchell i ll just change the image , forget about this image – usernan Jun 14 '16 at 10:44
  • @Piglet so thats the reason i am asking , how to fix it . Bez i have to work with that kind of white images , i dnt have choice – usernan Jun 14 '16 at 11:37
  • if i upload that white image on https://pixlr.com/ and if do auto adjust then i can see proper image . is it possible to do in image magic auto color or something like that – usernan Jun 14 '16 at 11:38
  • Please do not vandalize your post. Note that once you post a question or answer to this site, those posts become part of the collective efforts of others who have also contributed to that content. Posts that are potentially useful to others should not be removed except under extraordinary circumstances. Even if the post is no longer useful to the original author, that information is still beneficial to others who may run into similar problems in the future - this is the underlying philosophy of Stack Exchange. – Matt Jul 01 '16 at 10:37
  • @Matt i made mess of this question – usernan Jul 01 '16 at 10:39
  • @usernan: So post a new one. Deleting this question is not a prerequisite for posting a new question. – Matt Jul 01 '16 at 10:40

3 Answers3

14

If you want to do this with OpenCV, a good starting point may be after doing some simple processing to remove noise and small details in the image, you can find the edges of the image and then find the bounding box and crop to that area. But in case of your second image, you may need to do some post-processing as the raw edges may hold some noise and borders. You can do this on a pixel-by-pixel basis, or another maybe overkill method would be finding all the contours in the image and the finding the biggest bounding box. Using this you can get the following results: First Image

And for the second one:

Second Image

The part that needs work is finding a proper thresholding method that works for all the images. Here I used different thresholds to make a binary image, as the first one was mostly white and second one was a bit darker. A first guess would be using the average intensity as a clue.

Hope this helps!

Edit

This is how I used some pre-processing and also a dynamic threshold to get it work for both of the images:

im = cv2.imread('cloth.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
imgray = cv2.blur(imgray,(15,15))
ret,thresh = cv2.threshold(imgray,math.floor(numpy.average(imgray)),255,cv2.THRESH_BINARY_INV)
dilated=cv2.morphologyEx(thresh, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(10,10)))
_,contours,_ = cv2.findContours(dilated,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

I also checked the contour area to remove very large contours:

new_contours=[]
for c in contours:
    if cv2.contourArea(c)<4000000:
        new_contours.append(c)

The number 4000000 is an estimation of the image size (width*height), big contours should have an area close to the image size.

Then you can iterate all the contours, and find the overall bounding box:

best_box=[-1,-1,-1,-1]
for c in new_contours:
   x,y,w,h = cv2.boundingRect(c)
   if best_box[0] < 0:
       best_box=[x,y,x+w,y+h]
   else:
       if x<best_box[0]:
           best_box[0]=x
       if y<best_box[1]:
           best_box[1]=y
       if x+w>best_box[2]:
           best_box[2]=x+w
       if y+h>best_box[3]:
           best_box[3]=y+h

Then you have the bounding box of all contours inside the best_box array.

Here is the result for the third image: Third Image

Kamyar Infinity
  • 2,711
  • 1
  • 21
  • 32
  • hi thanks for answering question , i wanted to knw findContours function wil able to find Contours for 2nd image . if yes then how what will be parameters for that function – usernan Jun 16 '16 at 04:29
  • @usernan Yes, it can. I added the parameter values I used to make it work for both of images, to the answer. – Kamyar Infinity Jun 16 '16 at 04:50
  • u said that "checked the contour area to remove very large contours" , but above code i think will return all possible contours, how should select single contour that fits the object – usernan Jun 16 '16 at 11:53
  • @usernan I also added the code to remove very large contours. As you can see in the images, there's no single contour that matches the whole object, so what you need to do is iterate over all of the contours and find the smallest x and also the biggest y of all contours to find the appropriate bounding box. – Kamyar Infinity Jun 16 '16 at 21:57
  • thanks i just modified your code to get what i want . still i have one image which creates problem , plz help with this , i ll upload those images – usernan Jun 17 '16 at 05:13
  • that third images contains 2 sandals, both are not coming under single Contours . – usernan Jun 17 '16 at 07:00
  • @usernan You need to keep all of the contours, and process all of them to get the required bounding box. See my new edit. – Kamyar Infinity Jun 17 '16 at 20:42
  • wanted to knw , how to handle images which has shadows , bez some images create problem – usernan Jun 22 '16 at 05:33
  • @usernan what kind of problem? – Kamyar Infinity Jun 22 '16 at 05:34
  • that shadow is also consider as part of image – usernan Jun 22 '16 at 05:37
  • is there anyway that i can remove shadow or change color of background image to white so that shadow does not appear – usernan Jun 22 '16 at 05:47
  • If the cloth itself has dark colour, it's not easily possible, as the shadow looks like a part of the cloth. But for other cases, you may find the dark regions by transferring to HSV colour space, and selecting regions with low values in the Value channel. – Kamyar Infinity Jun 22 '16 at 05:51
  • i have used adaptiveThreshold whcih results in image which i uploaded in Edit 4 , but if i want to find contour on that , i am not getting it proper – usernan Jun 22 '16 at 06:05
  • I'm not sure about adaptiveThreshold, as you don't have many options with it. Did you use ADAPTIVE_THRESH_MEAN_C mode? This one should give more details in the final image. – Kamyar Infinity Jun 22 '16 at 20:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/115355/discussion-between-usernan-and-kamyar-infinity). – usernan Jun 23 '16 at 03:55
3

You can try isolating the saturation channel, and trim as expected.

# Convert to HSV, isolate saturation channel, and switch to format
# that supports extended paging.
convert source.jpg -colorspace HSV -channel S -separate /tmp/saturation.png

saturation channel

# Trim as before
convert /tmp/saturation.png -trim /tmp/trim.png

trim

# Capture results of -trim
GEO=$(identify -format '%wx%h%X%Y' /tmp/trim.png)

1232x1991+384+336

# Apply results to original image
convert source.jpg -crop $GEO trim.jpg

finish

emcconville
  • 23,800
  • 4
  • 50
  • 66
2

The problem with Kamyar Infinity's method is when some area of background' color is close to the object, you can't get the right boundary of the object.

The threshold value which is set to math.floor(numpy.average(imgray)) won't help you... eg:

enter image description here

Even though thresh value is perfect(manually adjust), you can't overlook that little point on the top right of the image. You need to filter out some areas. eg:

enter image description here

Method to achieve this was given by the opencv officially.

Creating Bounding boxes and circles for contours

Another method was given here could be useful. (basically same with Kamyar Infinity but added cv.inRandge)

Dealing with contours and bounding rectangle in OpenCV 2.4 - python 2.7

Jay
  • 738
  • 8
  • 14