0

enter image description here

I'm having trouble cropping out the pink line on the image. Ideally, I want to crop it the entire pink stretch, it's okay if the blue is included.

What I did

import cv2
import numpy as np 
from PIL import Image, ImageFilter

#convertes image to hsv and applies blur
img = cv2.imread("1501.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2RGB)
fin = cv2.GaussianBlur(hsv,(25,25),cv2.BORDER_DEFAULT)

#divided the image in half to see the target
na = np.array(fin)
orig = na.copy()
m = orig.shape[0]
n = orig.shape[1]/2
M = int(m)
N = int(n)
tiles = [orig[x:x+M,y:y+N] for x in range(0,orig.shape[0]) for y in range(0,orig.shape[1],N)]
variable = tiles[0]
Image.fromarray(variable).save('variable.jpg')

#extracts color from the target
hsv_lower = (300,2.2,71)
hsv_upper = (326,41,32.5)
mask = cv2.inRange(variable, hsv_lower, hsv_upper)

What to do next I'm not sure what to do next, and am unsure if I'm even capturing the pink line in the first place. Python3 solutions are preferred.

sameerp815
  • 51
  • 1
  • 4
  • 2
    `hsv = cv2.cvtColor(img, cv2.COLOR_RGB2RGB)`? Don't you mean `cv2.COLOR_BGR2HSV`? Also, please pay attention to the documentation on [color conversions](https://docs.opencv.org/4.5.1/de/d25/imgproc_color_conversions.html): The `H` value is set to the range `[0 ... 180]` for common 8-bit images. You might want to have a look [this earlier answer from me](https://stackoverflow.com/a/55827176/11089932) as a starting point on color thresholding using the HSV/HLS color space. – HansHirse Feb 01 '21 at 07:33

1 Answers1

0

You can use findContours to segment out a thresholded blob.

Thresholded Image:

enter image description here

Filter Contours by size:

enter image description here

Crop out the contour:

enter image description here

I have no idea why the color in the output image is blue. If anyone else knows why this is happening I'd love to know because it's driving me a little crazy.

Code:

import cv2
import numpy as np

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

# rescale
scale = 0.25;
h, w = img.shape[:2];
h = int(h*scale);
w = int(w*scale);
img = cv2.resize(img, (w,h));

# hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV);
h, s, v = cv2.split(hsv);

# thresh
thresh = cv2.inRange(h, 140, 160);

# contours
_, contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);

# filter contours by size
big_cntrs = [];
marked = img.copy();
for contour in contours:
    area = cv2.contourArea(contour);
    if area > 10000:
        print(area);
        big_cntrs.append(contour);
cv2.drawContours(marked, big_cntrs, -1, (0, 255, 0), 3);

# create a mask of the contoured image
mask = np.zeros_like(h);
mask = cv2.drawContours(mask, big_cntrs, -1, 255, -1);

# crop out
out = np.zeros_like(img) # Extract out the object and place into output image
out[mask == 255] = img[mask == 255];

# show
cv2.imshow("Original", img);
cv2.imshow("thresh", thresh);
cv2.imshow("Marked", marked);
cv2.imshow("out", out);
cv2.waitKey(0);

# save
cv2.imwrite("thresh.png", thresh);
cv2.imwrite("marked.png", marked);
cv2.imwrite("out.png", out);

Edit:

Fixed the blue color issue (changed to "mask = np.zeros_like(h);").

I'm using OpenCV 3.4.2

Ian Chu
  • 2,924
  • 9
  • 14
  • 1
    The problem is located here: `mask = np.zeros_like(img)` and `mask = cv2.drawContours(mask, big_cntrs, -1, 255, -1)`. You initialize a three channel image, but only write to the first channel, such that mask is all empty in the second and third channel. Thus, `out[mask == 255] = img[mask == 255]` only copies the first channel, which is blue since OpenCV uses BGR color ordering. On another issue: Python doesn't need trailing `;`. Also, you seem to use OpenCV 3.x.x (cf. your `findContours` call). You should state that, since people won't get your code running when using the newest 4.x.x version. – HansHirse Feb 01 '21 at 19:21