0

I'm using opencv right now to display different colours by masking everything but that colour. What I want to achieve is to get all the pixel coordinates that are green, black etc. Some screenshots: image of a black line

enter image description here

the first image is of a black line and the second image is of a green square. I would like to be able to record the pixel coordinates that have black or green on them. Here's the main code:

import sys
sys.path.append("\Python\Opencv_codes")
import line_following_testing as lf

from line_following_testing import lower_green as lg
from line_following_testing import upper_green as ug

from line_following_testing import lower_black as lb
from line_following_testing import upper_black as ub

import numpy as np
from time import sleep as wait
import cv2
from PIL import Image

green_boundaries = [
    ([75, 52, 60], [106, 255, 255])
    ]

cap = cv2.VideoCapture(0)

while True:
    _, img = cap.read()

    lf.percentage_calculator(green_boundaries, "green", img)

    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    #cropping and getting the hsv value and converting it to see of the value is their
    mask = cv2.inRange(hsv, lg, ug)
    green_result = cv2.bitwise_and(hsv, hsv, mask=mask)

    #cropping and getting the hsv value and converting it to see of the value is their
    mask1 = cv2.inRange(hsv, lb, ub)
    black_result = cv2.bitwise_and(hsv, hsv, mask=mask1)
    black_canny = cv2.Canny(black_result, 700,900)

    cv2.imshow("green", green_result)
    cv2.imshow('black', black_result)
    cv2.imshow("hsv", hsv)
    cv2.imshow('img', img)
    cv2.imshow('black_canny', black_canny)


    k = cv2.waitKey(30) & 0xff
    if k==27:
        break


and here is the imported script:

import numpy as np
from time import sleep as wait
import cv2
from PIL import Image

lower_green = np.array([75, 52, 60])
upper_green = np.array([106, 255, 255])

lower_black = np.array([0,0,0])
upper_black = np.array([180,255,45])

def percentage_calculator(boundaries, colour, image):

    for(lower, upper) in boundaries:

        lower = np.array(lower)
        upper = np.array(upper)

        # finds colors in boundaries a applies a mask
        mask = cv2.inRange(image, lower, upper)
        output = cv2.bitwise_and(image, image, mask = mask)

        tot_pixel = image.size
        pixel = np.count_nonzero(output)
        percentage = round(pixel * 100 / tot_pixel, 2)

        print(colour + " pixels: " + str(pixel))
        print("Total pixels: " + str(tot_pixel))
        print("Percentage of " + colour + " pixels: " + str(percentage) + "%")

New code:

import sys
sys.path.append("\Python\Opencv_codes")
import line_following_testing as lf

from line_following_testing import lower_green as lg
from line_following_testing import upper_green as ug

from line_following_testing import lower_black as lb
from line_following_testing import upper_black as ub

import numpy as np
from time import sleep as wait
import cv2

green_boundaries = [
    ([75, 52, 60], [106, 255, 255])
    ]

cap = cv2.VideoCapture(0)

while True:
    _, img = cap.read()

    lf.percentage_calculator(green_boundaries, "green", img)

    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    #cropping and getting the hsv value and converting it to see of the value is their
    mask = cv2.inRange(hsv, lg, ug)
    green_result = cv2.bitwise_and(hsv, hsv, mask=mask)

    #cropping and getting the hsv value and converting it to see of the value is their
    mask1 = cv2.inRange(hsv, lb, ub)
    black_result = cv2.bitwise_and(hsv, hsv, mask=mask1)
    x, y = mask1[-5:].nonzero()
    x_min = min(x)
    x_max = max(x)
    y_min = min(y)
    y_max = max(y)

    center_coords_min = (x_min, y_min)
    center_coords_max = (x_max, y_max)

    cv2.circle(img, center_coords_min, 10, (0, 0, 255), 2)
    cv2.circle(img, center_coords_max, 10, (255, 0, 0), 2)
    print(x_min, y_min)
    print(x_max, y_max)
    black_canny = cv2.Canny(black_result, 700,900)

    cv2.imshow("green", green_result)
    cv2.imshow('black', black_result)
    cv2.imshow("hsv", hsv)
    cv2.imshow('img', img)
    cv2.imshow('black_canny', black_canny)


    k = cv2.waitKey(30) & 0xff
    if k==27:
        break
Noah Robb
  • 59
  • 1
  • 7
  • why do you need it? You have `mask` as `numpy.array` so you could use `numpy` functions for this - maybe `.where()` or `.nonzero()` ? - See more [numpy get index where value is true](https://stackoverflow.com/questions/16094563/numpy-get-index-where-value-is-true) - it may need only to convert `mask` to `True/False` like `mask != 0` – furas Apr 04 '22 at 09:29
  • I'm trying to make a line following robot and to do so I want to get the pixels coords that are black and get the farthest pixel on the x coord and the least farthest pixel on the x coord then use those numbers to keep the line in the middle. I hope this makes sense – Noah Robb Apr 04 '22 at 09:46
  • line for following robot makes sense. And I think it would need to check x only in few nearest rows - ie 5 rows - `x, y = mask[-5:].nonzero` and `min(x), max(x)` or middle `(min(x) + max(x))/2` – furas Apr 04 '22 at 10:18
  • I'm tying to use the x, y = mask[-5:].nonzero however, every time I try to use it there is either nothing in the x or it works but not properly (the coords arent where they should be). I was also trying to use countors but those are too far out of my knowledge so I'm trying to stick with the first method. I've updated the question to show the new code – Noah Robb Apr 05 '22 at 04:11
  • your question lacks error messages. that is why you ask, right? -- for numpy, indices are **first y then x** (i, j). -- you must debug your code before you ask. when you do that, you learn to understand the code you wrote. understanding your own program is generally a good idea. -- such long questions also have a low chance of getting responses. please review [ask] and [mre]. – Christoph Rackwitz Apr 15 '22 at 07:08

1 Answers1

0

Using this code get all colors hsv !

import cv2
import numpy as np

img_path = r"img_path"


def nothing(x):
    pass


def crop_image_contours(image_copy):
    cropped_image = None
    # convert the image to grayscale format
    img_gray = cv2.cvtColor(image_copy, cv2.COLOR_BGR2GRAY)

    # apply binary thresholding
    ret, thresh = cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY)
    contours1, hierarchy1 = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    buckle = []
    # computes the bounding box for the contour, and draws it on the frame,
    for contour in contours1:
        # Find bounding rectangles
        if cv2.contourArea(contour) > 100:
            box = cv2.minAreaRect(contour)
            box = cv2.boxPoints(box)
            box = np.array(box, dtype="int")
            x, y, w, h = cv2.boundingRect(contour)
            cropped_image = image_copy[y:y+h, x:x+w]
            buckle.append(box)
    return cropped_image


def crop_img(image, coord):
    image_cpy = image.copy()
    cropped_image = image_cpy[coord[1]:coord[3], coord[0]:coord[2]]
    return cropped_image


def check_sum(image, coord, hsv_value):
    c_image = crop_img(image, coord)
    [[l_h, l_s, l_v], [u_h, u_s, u_v]] = hsv_value
    lower_range = np.array([l_h, l_s, l_v])
    upper_range = np.array([u_h, u_s, u_v])
    img_crop = cv2.cvtColor(c_image, cv2.COLOR_BGR2HSV)
    val = cv2.inRange(img_crop, lower_range, upper_range)
    hsv_score = val.sum()
    # print(hsv_score)


useCamera = False

cv2.namedWindow('image')

# create trackbars for color change
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)  # Hue is from 0-179 for Opencv
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)

# Set default value for MAX HSV trackbars.
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)

# Initialize to check if HSV min/max value changes
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0

# Output Image to display
if useCamera:
    cap = cv2.VideoCapture(0)
    # Wait longer to prevent freeze for videos.
    waitTime = 330
else:
    img = cv2.imread(img_path)
    output = img
    waitTime = 33

while True:

    if useCamera:
        # Capture frame-by-frame
        ret, img = cap.read()
        output = img

    # get current positions of all trackbars
    hMin = cv2.getTrackbarPos('HMin', 'image')
    sMin = cv2.getTrackbarPos('SMin', 'image')
    vMin = cv2.getTrackbarPos('VMin', 'image')

    hMax = cv2.getTrackbarPos('HMax', 'image')
    sMax = cv2.getTrackbarPos('SMax', 'image')
    vMax = cv2.getTrackbarPos('VMax', 'image')

    # Set minimum and max HSV values to display
    lower = np.array([hMin, sMin, vMin])
    upper = np.array([hMax, sMax, vMax])

    # Create HSV Image and threshold into a range.
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    output = cv2.bitwise_and(img, img, mask=mask)

    # Print if there is a change in HSV value
    if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax)):
        print("[[ %d , %d, %d],[%d , %d, %d]]" % (hMin, sMin, vMin, hMax, sMax,vMax))
        phMin = hMin
        psMin = sMin
        pvMin = vMin
        phMax = hMax
        psMax = sMax
        pvMax = vMax
        clr_val = [[phMin, psMin, pvMin], [phMax, psMax, pvMax]]
    cv2.imshow('image', output)
    # Wait longer to prevent freeze for videos.
    if cv2.waitKey(waitTime) & 0xFF == ord('q'):
        break

# Release resources
if useCamera:
    cap.release()
cv2.destroyAllWindows()
Parthiban Marimuthu
  • 665
  • 1
  • 8
  • 15
  • I'm tying to use the x, y = mask[-5:].nonzero however, every time I try to use it there is either nothing in the x or it works but not properly (the coords arent where they should be). I was also trying to use countors but those are too far out of my knowledge so I'm trying to stick with the first method. I've updated the question to show the new code. – Noah Robb Apr 05 '22 at 04:09