Bottle cap control with NVIDIA Jetson and OpenCV

Hello to everyone,

I have a bottle, but the color of the bottle is white and the cap color cannot be distinguished by the color detection method. I tried two different methods but without success. I am sharing the picture of the bottle and cap below. Here are the codes I use. Which method can I use? Thanks in advance for your help.

Photo;
sise2

METHOD 1 
import cv2

import numpy as np 

def gstreamer_pipeline(

    capture_width=1280,

    capture_height=720,

    display_width=400,

    display_height=400,

    framerate=0,

    flip_method=0,

):

    return (

        "nvarguscamerasrc ! "

        "video/x-raw(memory:NVMM), "

        "width=(int)%d, height=(int)%d, "

        "format=(string)NV12, framerate=(fraction)%d/1 ! "

        "nvvidconv flip-method=%d ! "

        "video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "

        "videoconvert ! "

        "video/x-raw, format=(string)BGR ! appsink"

        % (

            capture_width,

            capture_height,

            framerate,

            flip_method,

            display_width,

            display_height,

        )

    )

cap = cv2.VideoCapture(gstreamer_pipeline(flip_method=0), cv2.CAP_GSTREAMER) 

_, frame = cap.read()

rows, cols, _ = frame.shape

x_medium = int(cols/2)

y_medium = int(cols/2)

w_medium = int(cols/2)

h_medium = int(cols/2)

center = int(cols/2) 

x_medium1 = int(cols/2)

y_medium1 = int(cols/2)

w_medium1 = int(cols/2)

h_medium1 = int(cols/2)

center1 = int(cols/2) 

while True:

    _, frame = cap.read()

    hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 

    low_abc = np.array([10, 20, 0]) 

    high_abc = np.array([20, 255, 255]) 

    abc_mask= cv2.inRange(hsv_frame, low_abc, high_abc)

    (contours), _ = cv2.findContours(abc_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    contours = sorted(contours, key = lambda x:cv2.contourArea(x), reverse= True)

    for cnt in contours:

        (x, y, w, h) = cv2.boundingRect(cnt)

        x_medium = int((x+x+w)/2)

        break

    low_white = np.array([0, 0, 0]) 

    high_white= np.array([0, 0, 255]) 

    white_mask = cv2.inRange(hsv_frame, low_white, high_white)

    (contours1), _ = cv2.findContours(white_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    contours1 = sorted(contours1, key = lambda x1:cv2.contourArea(x1), reverse= True)

    for cnt1 in contours1:

        (x1, y1, w1, h1) = cv2.boundingRect(cnt1)

        x_medium1 = int((x1+x1+w1)/2)

        break

    if x_medium1 < x_medium:

        cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0),2)

        cv2.putText(frame,"CAP", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0))

    else:

        cv2.rectangle(frame, (x1,y1), (x1+w1,y1+h1), (0,0,255),2)

        cv2.putText(frame,"NO CAP", (x1,y1), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255))

    cv2.imshow("Frame", frame)

    key = cv2.waitKey(1)

    if key == 27:

        break

cap.release()

cv2.destroyAllWindows()
METHOD 2
import cv2

import numpy as np 

def gstreamer_pipeline(

    capture_width=1280,

    capture_height=720,

    display_width=680,

    display_height=500,

    framerate=0,

    flip_method=0,

):

    return (

        "nvarguscamerasrc ! "

        "video/x-raw(memory:NVMM), "

        "width=(int)%d, height=(int)%d, "

        "format=(string)NV12, framerate=(fraction)%d/1 ! "

        "nvvidconv flip-method=%d ! "

        "video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "

        "videoconvert ! "

        "video/x-raw, format=(string)BGR ! appsink"

        % (

            capture_width,

            capture_height,

            framerate,

            flip_method,

            display_width,

            display_height,

        )

    )

cap = cv2.VideoCapture(gstreamer_pipeline(flip_method=0), cv2.CAP_GSTREAMER) 

while True:

    _, frame = cap.read()

    # Belt 

    belt = frame[209: 457, 137: 530]

    gray_belt = cv2.cvtColor(belt, cv2.COLOR_BGR2GRAY)

    _, threshold = cv2.threshold(gray_belt, 110, 255, cv2.THRESH_BINARY)

    # Detect the Nuts

    (contours), _ = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for cnt in contours:

        (x, y, w, h) = cv2.boundingRect(cnt)

        # Calculate area

        area = cv2.contourArea(cnt)

        # Distinguish small and big nuts 

        if area > 500:

            # Big nut

            cv2.rectangle(belt, (x, y), (x + w, y + h), (0, 0, 255), 2)

        elif 100 < area < 500:

            cv2.rectangle(belt, (x, y), (x + w, y + h), (255, 0, 0), 2)

        cv2.putText(belt, str(area), (x, y), 1, 1, (0, 255, 0))

    cv2.imshow("Frame", frame)

    cv2.imshow("Belt", belt)

    cv2.imshow("Threshold", threshold)

    key = cv2.waitKey(1)

    if key == 27:

        break

cap.release()

cv2.destroyAllWindows()

opencv, opencvpython

those are meaningless tags on this forum. don’t use meaningless tags please. I’ve fixed that up.

your code has a lot wrong with it. it’s not salvageable.

and what do you mean by “control”?

your first error was putting a white object in front of a white background.

I’m sorry for mistake. I showed the photo as representative. Normally the background is black. Status whether the cover I want to check exists.
Sorry again for the mistake.

to select white pixels using inRange, select

  • H: all hues (they don’t matter)
  • S: low saturation (lack of color)
  • V: high value (bright)