-1

I have a set of skin lesion images, and I'm using OpenCV in python to detect the lesion and crop around it thus reducing the size (the images have a lot of skin area that can be cropped out).

However I can't figure out how to have the resulting cropped image in a square shape. Any help would be appreciated.

So far I have slightly edited the code from this question: How to crop the biggest object in image with python opencv?

Here's a sample image... I tried to get the most normal SFW lesion I could find, sorry if it grosses anybody out: https://i.stack.imgur.com/fqt1g.jpg

And here's the code. I have been adding to x, y, w, h (ie. x+20 etc) to see if I can get it into a square shape but I don't think that's the way to do it.


import cv2
import numpy as np

# load image
img = cv2.imread("ISIC_0024313.jpg")

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert to grayscale
# threshold to get just the signature (INVERTED)
retval, thresh_gray = cv2.threshold(gray, thresh=160, maxval=255, \
                                   type=cv2.THRESH_BINARY_INV)

image, contours, hierarchy = cv2.findContours(thresh_gray,cv2.RETR_LIST, \
                                   cv2.CHAIN_APPROX_SIMPLE)

# Find object with the biggest bounding box
mx = (0,0,0,0)      # biggest bounding box so far
mx_area = 0
for cont in contours:
    x,y,w,h = cv2.boundingRect(cont)
    x, y, w, h = x-40, y-40, w+80,h+80 # make the bounding box a bit bigger
    area = w*h
    if area > mx_area:
        mx = x,y,w,h
        mx_area = area
x,y,w,h = mx

# Output to files
roi=img[y:y+h,x:x+w]

cv2.imshow("im",roi)
cv2.waitKey(0)

cv2.imwrite("cropped.png", roi)

And here's the output. Close but not close enough: https://i.stack.imgur.com/iLWN8.png

How exactly can I ensure that the resulting crop is square? While also giving enough breathing space to encompass the whole lesion.

Thanks

SCool
  • 3,104
  • 4
  • 21
  • 49
  • all answers must include some simple bounds checking. ie. will min-x/y or max-x/y go off the edge of the image. my suggestion is to not do your padding(-40 etc) until you make it square, then if there is room, pad it out. I would also start by centering by using half the difference of h/w so it's moreorless centered. Also, if you're looking to create data for a classifier, you may wish to store the coords separately and NOT crop....this will allow some dynamic crops made by a generator. – user1269942 Mar 26 '19 at 22:08
  • @user1269942 waiting to pad until I make a square sounds like a good idea, just need to figure out how to make a square. – SCool Mar 26 '19 at 22:50

1 Answers1

0

Can you just check to see which is bigger between h and w and set both equal before you select the sub array? Something like:

if h > w:
    w = h
else:
    h = w

# Then select the sub-array:
roi=img[y:y+h,x:x+w]
it's-yer-boy-chet
  • 1,917
  • 2
  • 12
  • 21