You can get better results from range thresholding than you're currently getting. Additionally, try using the morphological operations like opening and closing after thresholding to remove spurious bits and add in any pieces you didn't mean to remove.
These were the results I was able to get through thresholding with cv2.inRange() and applying opening and closing with cv2.morphologyEx():
image 1 yellow, image 1 blue, image 2 yellow, image 2 blue
Here was my code for the first image:
import cv2
import numpy as np
img = cv2.imread('0.jpg')
# crop out the top of the image where the scores are
h, w = img.shape[:2]
score_h = int(h/8)
img = img[score_h:h, :]
h, w = img.shape[:2]
# blur for better thresholding
blur = cv2.GaussianBlur(img, (5,5), 1)
# threshold in HSV space
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)
# threshold for yellow
lb_y = np.array([11, 0, 153])
ub_y = np.array([52, 255, 255])
bin_y = cv2.inRange(hsv, lb_y, ub_y)
# cv2.imshow("thresh yellow", bin_y)
# cv2.waitKey(0)
# open to remove spurious yellow bits
open_kern = np.ones((3,3), dtype=np.uint8)
bin_y = cv2.morphologyEx(bin_y, cv2.MORPH_OPEN, open_kern, iterations=2)
# cv2.imshow("opened yellow", bin_y)
# cv2.waitKey(0)
# threshold for blue
lb_b = np.array([113, 41, 191])
ub_b = np.array([119, 76, 232])
bin_b = cv2.inRange(hsv, lb_b, ub_b)
# cv2.imshow("thresh blue", bin_b)
# cv2.waitKey(0)
# open to remove spurious blue bits
kern = np.ones((3,3), dtype=np.uint8)
bin_b = cv2.morphologyEx(bin_b, cv2.MORPH_OPEN, kern, iterations=2)
# cv2.imshow("opened blue", bin_b)
# cv2.waitKey(0)
# combine to show yellow detection
rip_y = img.copy()
rip_y[bin_y==0] = 0
mark_y = cv2.addWeighted(img, .4, rip_y, .6, 1)
cv2.imshow("marked yellow", mark_y)
cv2.waitKey(0)
# cv2.imwrite('0-y.jpg',mark_y)
# combine to show blue detection
rip_b = img.copy()
rip_b[bin_b==0] = 0
mark_b = cv2.addWeighted(img, .4, rip_b, .6, 1)
cv2.imshow("marked blue", mark_b)
cv2.waitKey(0)
# cv2.imwrite('0-b.jpg',mark_b)
And for the second:
import cv2
import numpy as np
img = cv2.imread('1.jpg')
# crop out the top of the image where the scores are
h, w = img.shape[:2]
score_h = int(h/10)
img = img[score_h:h, :]
h, w = img.shape[:2]
# blur for better thresholding
blur = cv2.GaussianBlur(img, (5,5), 1)
# threshold in HSV space
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)
# threshold for yellow
lb_y = np.array([14, 79, 140])
ub_y = np.array([25, 255, 217])
bin_y = cv2.inRange(hsv, lb_y, ub_y)
# cv2.imshow("thresh yellow", bin_y)
# cv2.waitKey(0)
# open to remove spurious yellow bits
open_kern = np.ones((3,3), dtype=np.uint8)
bin_y = cv2.morphologyEx(bin_y, cv2.MORPH_OPEN, open_kern, iterations=2)
# cv2.imshow("opened yellow", bin_y)
# cv2.waitKey(0)
# threshold for blue
lb_b = np.array([113, 50, 150])
ub_b = np.array([135, 255, 255])
bin_b = cv2.inRange(hsv, lb_b, ub_b)
# cv2.imshow("thresh blue", bin_b)
# cv2.waitKey(0)
# close to fill in blue lines
kern = np.ones((3,3), dtype=np.uint8)
bin_b = cv2.morphologyEx(bin_b, cv2.MORPH_CLOSE, kern, iterations=2)
# cv2.imshow("closed blue", bin_b)
# cv2.waitKey(0)
# open to remove spurious lines
bin_b = cv2.morphologyEx(bin_b, cv2.MORPH_OPEN, kern, iterations=2)
# cv2.imshow("opened blue", bin_b)
# cv2.waitKey(0)
# combine to show yellow detection
rip_y = img.copy()
rip_y[bin_y==0] = 0
mark_y = cv2.addWeighted(img, .4, rip_y, .6, 1)
cv2.imshow("marked yellow", mark_y)
cv2.waitKey(0)
cv2.imwrite('1-y.jpg',mark_y)
# combine to show blue detection
rip_b = img.copy()
rip_b[bin_b==0] = 0
mark_b = cv2.addWeighted(img, .4, rip_b, .6, 1)
cv2.imshow("marked blue", mark_b)
cv2.waitKey(0)
cv2.imwrite('1-b.jpg',mark_b)
The first and the second are identical aside from their threshold values, and the second image I am applying a closing operation on the blue (not done for the other three thresholds) to close up the gaps in the line a bit.
It's not clear whether you're looking to do this automatically or manually for a few images. If you're looking to do it automatically, my first go-to would be to create a set of threshold values that work relatively well for all the images, and be harsh with morphological operations. This will likely thin out the lines a good bit, but then you could use numpy operations to fit a curve to the lines, and then widen it to achieve roughly the same line.
If you're going to be doing it manually, then the easiest bet is to play around with threshold values for each image. I've just recently created a tool that gives you sliders for changing the threshold range and previewing it on the fly. Check it out on GitHub if you're interested in trying it out. It will output the binary thresholded image, the colorspace you're thresholding in, and the lower and upper bounds that were used for thresholding.
isolate certain colored lines(the field lines)but you don't show the original image or what you want