1.Tìm hiểu về không gian màu HSV hay HSB
Ngoài hệ màu hệ màu RGB chúng ta có hệ màu HSV để giúp việc lọc màu tốt hơn. Cụ thể với màu sắc có bóng tối dần thì hệ màu RGB không phát hiện ra được.Trong thực tế để lọc màu có độ bóng do chiếu sáng mức độ sáng tối của vật không đều, chúng ta sử dụng hệ màu HSV. Hệ màu HSV bao gồm :
- H: (Hue) Vùng màu
- S: (Saturation) Độ bão hòa màu
- V (hay B): (Bright hay Value) độ sáng
-
-
2. Công cụ Gui Trackbar : để thuận tiện thay đổi giá trị biến nhập vào từ ngừời dùng , OpenCV cung cấp công cụ trackbar ví dụ như hình dưới:
3.Tiến hành viết code:
bước 1: Khai báo thư viện sử dụng và hàm callback cho trackbar
123456789101112# Cai thu vien can thu can thiet<strong><span style="color: #993300;">from collections import deque</span></strong><strong><span style="color: #993300;">from imutils.video import VideoStream</span></strong><strong><span style="color: #993300;">import numpy as np</span></strong><strong><span style="color: #993300;">import argparse</span></strong><strong><span style="color: #993300;">import cv2</span></strong><strong><span style="color: #993300;">import imutils</span></strong><strong><span style="color: #993300;">import time</span></strong><strong><span style="color: #993300;">def callback(x):</span></strong><strong><span style="color: #993300;"> pass</span></strong>
bước 2: Khai báo dải giá trị của H,S,V và tên của cửa sổ hiển thi trackbar
1 2 3 4 5 6 7 8 9 10 |
<span style="color: #993300;"><strong># khai bao gia tri low, high cua dai mau</strong></span> <span style="color: #993300;"><strong>ilowH = 0</strong></span> <span style="color: #993300;"><strong>ihighH = 179</strong></span> <span style="color: #993300;"><strong>ilowS = 0</strong></span> <span style="color: #993300;"><strong>ihighS = 255</strong></span> <span style="color: #993300;"><strong>ilowV = 0</strong></span> <span style="color: #993300;"><strong>ihighV = 255</strong></span> <span style="color: #993300;"><strong>cv2.namedWindow('image')</strong></span> |
bước 3 : Khởi tạo trackbar, tập hợp hàng đợi các điểm tracking, khởi tạo camera
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<strong><span style="color: #993300;"># Tao trackbar thay doi dai mau</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('lowH', 'image', ilowH, 179, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('highH', 'image', ihighH, 179, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('lowS', 'image', ilowS, 255, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('highS', 'image', ihighS, 255, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('lowV', 'image', ilowV, 255, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('highV', 'image', ihighV, 255, callback)</span></strong> <strong><span style="color: #993300;">pts = deque(maxlen=64) # khai bao tap hop cac diem</span></strong> <strong><span style="color: #993300;">vs = VideoStream(src=0).start()</span></strong> <strong><span style="color: #993300;">time.sleep(2.0)</span></strong> |
Bước 4: Tạo vòng lặp xử lý
-Đọc ảnh và đọc giá trị giới hạn của H,V,S
1 2 3 4 5 6 7 8 9 10 11 12 |
<strong><span style="color: #993300;"># doc frame anh</span></strong> <strong><span style="color: #993300;">frame = vs.read()</span></strong> <strong><span style="color: #993300;"># Lay gia tri low, high tu trackbar</span></strong> <strong><span style="color: #993300;">ilowH = cv2.getTrackbarPos('lowH', 'image')</span></strong> <strong><span style="color: #993300;">ihighH = cv2.getTrackbarPos('highH', 'image')</span></strong> <strong><span style="color: #993300;">ilowS = cv2.getTrackbarPos('lowS', 'image')</span></strong> <strong><span style="color: #993300;">ihighS = cv2.getTrackbarPos('highS', 'image')</span></strong> <strong><span style="color: #993300;">ilowV = cv2.getTrackbarPos('lowV', 'image')</span></strong> <strong><span style="color: #993300;">ihighV = cv2.getTrackbarPos('highV', 'image')</span></strong> <strong><span style="color: #993300;">rangeLower = (ilowH, ilowS, ilowV)</span></strong> <strong><span style="color: #993300;">rangeUpper = (ihighH, ihighS, ihighV)</span></strong> |
-Tiền xử lý ảnh và tìm đường bao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<strong><span style="color: #993300;">frame = imutils.resize(frame, width=600)</span></strong> <strong><span style="color: #993300;">(B, G, R) = frame[300, 200]</span></strong> <strong><span style="color: #993300;">blurred = cv2.GaussianBlur(frame, (11, 11), 0)</span></strong> <strong><span style="color: #993300;">hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)</span></strong> <strong><span style="color: #993300;"># Tien hanh loc anh theo dai mau, xoi mon va truong phinh anh</span></strong> <strong><span style="color: #993300;">mask = cv2.inRange(blurred, rangeLower, rangeUpper)</span></strong> <strong><span style="color: #993300;">mask = cv2.erode(mask, None, iterations=2)</span></strong> <strong><span style="color: #993300;">mask = cv2.dilate(mask, None, iterations=2)</span></strong> <strong><span style="color: #993300;"># tim duong vien vat sau khi loc mau</span></strong> <strong><span style="color: #993300;"># tinh tam cua duong tron bao quanh</span></strong> <strong><span style="color: #993300;">cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,</span></strong> <strong><span style="color: #993300;"> cv2.CHAIN_APPROX_SIMPLE)</span></strong> <strong><span style="color: #993300;">cnts = imutils.grab_contours(cnts)</span></strong> <strong><span style="color: #993300;">center = None</span></strong> <strong><span style="color: #993300;"># Chi xu ly anh khi it nhat 1 duong bao</span></strong> |
-Tìm đường bao lớn nhất, vẽ đường tròn kín nhỏ nhất bao quanh đường bao, tìm tâm vật, cập nhật tâm vào tập hợp điểm tracking
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<strong><span style="color: #993300;">if len(cnts) > 0:</span></strong> <strong><span style="color: #993300;"> # Tim duong bao co dien tich lon nhat</span></strong> <strong><span style="color: #993300;"> # Tinh toan tam duong tron co ban kinh nho nhat</span></strong> <strong><span style="color: #993300;"> c = max(cnts, key=cv2.contourArea)</span></strong> <strong><span style="color: #993300;"> ((x, y), radius) = cv2.minEnclosingCircle(c)</span></strong> <strong><span style="color: #993300;"> M = cv2.moments(c)</span></strong> <strong><span style="color: #993300;"> center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))</span></strong> <strong><span style="color: #993300;"> # Chi xu ly duong tron co ban kinh toi thieu</span></strong> <strong><span style="color: #993300;"> if radius > 10:</span></strong> <strong><span style="color: #993300;"> # ve duong tron va tam tren anh</span></strong> <strong><span style="color: #993300;"> # sau do cap nhat vi tri cua tam duong tron</span></strong> <strong><span style="color: #993300;"> cv2.circle(frame, (int(x), int(y)), int(radius) + 3,</span></strong> <strong><span style="color: #993300;"> (0, 255, 0), 3)</span></strong> <strong><span style="color: #993300;"> cv2.circle(frame, (int(x), int(y)), int(radius) + 6,</span></strong> <strong><span style="color: #993300;"> (0, 0, 255), 3)</span></strong> <strong><span style="color: #993300;"> cv2.circle(frame, (int(x), int(y)), int(radius) + 9,</span></strong> <strong><span style="color: #993300;"> (0, 255, 255), 3)</span></strong> <strong><span style="color: #993300;"> cv2.circle(frame, center, 5, (0, 0, 255), -1)</span></strong> <strong><span style="color: #993300;"># in len anh vi tri tam tron tracking</span></strong> <strong><span style="color: #993300;">cv2.putText(frame, "center(X={},Y={})".format(int(x), int(y)), (30, 30),</span></strong> <strong><span style="color: #993300;"> cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)</span></strong> <strong><span style="color: #993300;"># cap nhat cac diem tam duong tron</span></strong> <strong><span style="color: #993300;">pts.appendleft(center)</span></strong> |
-Tạo vòng lặp xử lý các điểm tracking
1 2 3 4 5 6 7 8 9 10 11 12 |
<strong><span style="color: #993300;"># vong lap xu ly cac diem dinh vi vi tri tam tron</span></strong> <strong><span style="color: #993300;">for i in range(1, len(pts)):</span></strong> <strong><span style="color: #993300;"> # 1 trong 2 diem lien tiep la diem rong thi tiep tuc</span></strong> <strong><span style="color: #993300;"> if pts[i - 1] is None or pts[i] is None:</span></strong> <strong><span style="color: #993300;"> continue</span></strong> <strong><span style="color: #993300;"> # ngoai ra thi tinh toan do rong cua duong diem tracking</span></strong> <strong><span style="color: #993300;"> # ve duong noi cac diem tracking</span></strong> <strong><span style="color: #993300;"> # tao hieu ung duoi sao choi</span></strong> <strong><span style="color: #993300;"> thickness = int(np.sqrt(121 / float(i + 1)) * 2.5)</span></strong> <strong><span style="color: #993300;"> thickness1 = int(np.sqrt(100 / float(i + 1)) * 1.5)</span></strong> <strong><span style="color: #993300;"> cv2.line(frame, pts[i - 1], pts[i], (0, 255, 255), thickness)</span></strong> <strong><span style="color: #993300;"> cv2.line(frame, pts[i - 1], pts[i], (0, 0, 255), thickness1)</span></strong> |
– Hiện cửa sổ chương trình và kết thúc chương trình
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<strong><span style="color: #993300;"> # hien anh</span></strong> <strong><span style="color: #993300;"> output = cv2.bitwise_and(frame, frame, mask=mask)</span></strong> <strong><span style="color: #993300;"> # hiển thị ảnh ghép giữa ảnh gốc và ảnh output</span></strong> <strong><span style="color: #993300;"> cv2.imshow("image", np.hstack([frame, output]))</span></strong> <strong><span style="color: #993300;"> key = cv2.waitKey(1) & 0xFF</span></strong> <strong><span style="color: #993300;"> # if the 'q' key is pressed, stop the loop</span></strong> <strong><span style="color: #993300;"> if key == ord("q"):</span></strong> <strong><span style="color: #993300;"> break</span></strong> <strong><span style="color: #993300;"># Dung camera</span></strong> <strong><span style="color: #993300;">vs.stop()</span></strong> <strong><span style="color: #993300;"># close all windows</span></strong> <strong><span style="color: #993300;">cv2.destroyAllWindows()</span></strong> |
Kết quả :
full code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
<strong><span style="color: #993300;"># Cai thu vien can thu can thiet</span></strong> <strong><span style="color: #993300;">from collections import deque</span></strong> <strong><span style="color: #993300;">from imutils.video import VideoStream</span></strong> <strong><span style="color: #993300;">import numpy as np</span></strong> <strong><span style="color: #993300;">import argparse</span></strong> <strong><span style="color: #993300;">import cv2</span></strong> <strong><span style="color: #993300;">import imutils</span></strong> <strong><span style="color: #993300;">import time</span></strong> <strong><span style="color: #993300;">def callback(x):</span></strong> <strong><span style="color: #993300;"> pass</span></strong> <strong><span style="color: #993300;"># khai bao gia tri low, high cua dai mau</span></strong> <strong><span style="color: #993300;">ilowH = 0</span></strong> <strong><span style="color: #993300;">ihighH = 179</span></strong> <strong><span style="color: #993300;">ilowS = 0</span></strong> <strong><span style="color: #993300;">ihighS = 255</span></strong> <strong><span style="color: #993300;">ilowV = 0</span></strong> <strong><span style="color: #993300;">ihighV = 255</span></strong> <strong><span style="color: #993300;">cv2.namedWindow('image')</span></strong> <strong><span style="color: #993300;"># Tao trackbar thay doi dai mau</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('lowH', 'image', ilowH, 179, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('highH', 'image', ihighH, 179, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('lowS', 'image', ilowS, 255, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('highS', 'image', ihighS, 255, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('lowV', 'image', ilowV, 255, callback)</span></strong> <strong><span style="color: #993300;">cv2.createTrackbar('highV', 'image', ihighV, 255, callback)</span></strong> <strong><span style="color: #993300;">pts = deque(maxlen=64) # khai bao tap hop cac diem</span></strong> <strong><span style="color: #993300;">vs = VideoStream(src=0).start()</span></strong> <strong><span style="color: #993300;">time.sleep(2.0)</span></strong> <strong><span style="color: #993300;">while True:</span></strong> <strong><span style="color: #993300;"> # doc frame anh</span></strong> <strong><span style="color: #993300;"> frame = vs.read()</span></strong> <strong><span style="color: #993300;"> # Lay gia tri low, high tu trackbar</span></strong> <strong><span style="color: #993300;"> ilowH = cv2.getTrackbarPos('lowH', 'image')</span></strong> <strong><span style="color: #993300;"> ihighH = cv2.getTrackbarPos('highH', 'image')</span></strong> <strong><span style="color: #993300;"> ilowS = cv2.getTrackbarPos('lowS', 'image')</span></strong> <strong><span style="color: #993300;"> ihighS = cv2.getTrackbarPos('highS', 'image')</span></strong> <strong><span style="color: #993300;"> ilowV = cv2.getTrackbarPos('lowV', 'image')</span></strong> <strong><span style="color: #993300;"> ihighV = cv2.getTrackbarPos('highV', 'image')</span></strong> <strong><span style="color: #993300;"> rangeLower = (ilowH, ilowS, ilowV)</span></strong> <strong><span style="color: #993300;"> rangeUpper = (ihighH, ihighS, ihighV)</span></strong> <strong><span style="color: #993300;"> if frame is None:</span></strong> <strong><span style="color: #993300;"> break</span></strong> <strong><span style="color: #993300;"> # dieu chinh kich thuoc anh, lam mo anh, chuyen doi anh sang HSV</span></strong> <strong><span style="color: #993300;"> frame = imutils.resize(frame, width=600)</span></strong> <strong><span style="color: #993300;"> (B, G, R) = frame[300, 200]</span></strong> <strong><span style="color: #993300;"> blurred = cv2.GaussianBlur(frame, (11, 11), 0)</span></strong> <strong><span style="color: #993300;"> hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)</span></strong> <strong><span style="color: #993300;"> # Tien hanh loc anh theo dai mau, xoi mon va truong phinh anh</span></strong> <strong><span style="color: #993300;"> mask = cv2.inRange(blurred, rangeLower, rangeUpper)</span></strong> <strong><span style="color: #993300;"> mask = cv2.erode(mask, None, iterations=2)</span></strong> <strong><span style="color: #993300;"> mask = cv2.dilate(mask, None, iterations=2)</span></strong> <strong><span style="color: #993300;"> # tim duong vien vat sau khi loc mau</span></strong> <strong><span style="color: #993300;"> # tinh tam cua duong tron bao quanh</span></strong> <strong><span style="color: #993300;"> cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,</span></strong> <strong><span style="color: #993300;"> cv2.CHAIN_APPROX_SIMPLE)</span></strong> <strong><span style="color: #993300;"> cnts = imutils.grab_contours(cnts)</span></strong> <strong><span style="color: #993300;"> center = None</span></strong> <strong><span style="color: #993300;"> # Chi xu ly anh khi it nhat 1 duong bao</span></strong> <strong><span style="color: #993300;"> if len(cnts) > 0:</span></strong> <strong><span style="color: #993300;"> # Tim duong bao co dien tich lon nhat</span></strong> <strong><span style="color: #993300;"> # Tinh toan tam duong tron co ban kinh nho nhat</span></strong> <strong><span style="color: #993300;"> c = max(cnts, key=cv2.contourArea)</span></strong> <strong><span style="color: #993300;"> ((x, y), radius) = cv2.minEnclosingCircle(c)</span></strong> <strong><span style="color: #993300;"> M = cv2.moments(c)</span></strong> <strong><span style="color: #993300;"> center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))</span></strong> <strong><span style="color: #993300;"> # Chi xu ly duong tron co ban kinh toi thieu</span></strong> <strong><span style="color: #993300;"> if radius > 10:</span></strong> <strong><span style="color: #993300;"> # ve duong tron va tam tren anh</span></strong> <strong><span style="color: #993300;"> # sau do cap nhat vi tri cua tam duong tron</span></strong> <strong><span style="color: #993300;"> cv2.circle(frame, (int(x), int(y)), int(radius) + 3,</span></strong> <strong><span style="color: #993300;"> (0, 255, 0), 3)</span></strong> <strong><span style="color: #993300;"> cv2.circle(frame, (int(x), int(y)), int(radius) + 6,</span></strong> <strong><span style="color: #993300;"> (0, 0, 255), 3)</span></strong> <strong><span style="color: #993300;"> cv2.circle(frame, (int(x), int(y)), int(radius) + 9,</span></strong> <strong><span style="color: #993300;"> (0, 255, 255), 3)</span></strong> <strong><span style="color: #993300;"> cv2.circle(frame, center, 5, (0, 0, 255), -1)</span></strong> <strong><span style="color: #993300;"> # in len anh vi tri tam tron tracking</span></strong> <strong><span style="color: #993300;"> cv2.putText(frame, "center(X={},Y={})".format(int(x), int(y)), (30, 30),</span></strong> <strong><span style="color: #993300;"> cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)</span></strong> <strong><span style="color: #993300;"> # cap nhat cac diem tam duong tron</span></strong> <strong><span style="color: #993300;"> pts.appendleft(center)</span></strong> <strong><span style="color: #993300;"> # vong lap xu ly cac diem dinh vi vi tri tam tron</span></strong> <strong><span style="color: #993300;"> for i in range(1, len(pts)):</span></strong> <strong><span style="color: #993300;"> # 1 trong 2 diem lien tiep la diem rong thi tiep tuc</span></strong> <strong><span style="color: #993300;"> if pts[i - 1] is None or pts[i] is None:</span></strong> <strong><span style="color: #993300;"> continue</span></strong> <strong><span style="color: #993300;"> # ngoai ra thi tinh toan do rong cua duong diem tracking</span></strong> <strong><span style="color: #993300;"> # ve duong noi cac diem tracking</span></strong> <strong><span style="color: #993300;"> # tao hieu ung duoi sao choi</span></strong> <strong><span style="color: #993300;"> thickness = int(np.sqrt(121 / float(i + 1)) * 2.5)</span></strong> <strong><span style="color: #993300;"> thickness1 = int(np.sqrt(100 / float(i + 1)) * 1.5)</span></strong> <strong><span style="color: #993300;"> cv2.line(frame, pts[i - 1], pts[i], (0, 255, 255), thickness)</span></strong> <strong><span style="color: #993300;"> cv2.line(frame, pts[i - 1], pts[i], (0, 0, 255), thickness1)</span></strong> <strong><span style="color: #993300;"> # hien anh</span></strong> <strong><span style="color: #993300;"> output = cv2.bitwise_and(frame, frame, mask=mask)</span></strong> <strong><span style="color: #993300;"> # hiển thị ảnh ghép giữa ảnh gốc và ảnh output</span></strong> <strong><span style="color: #993300;"> cv2.imshow("image", np.hstack([frame, output]))</span></strong> <strong><span style="color: #993300;"> key = cv2.waitKey(1) & 0xFF</span></strong> <strong><span style="color: #993300;"> # if the 'q' key is pressed, stop the loop</span></strong> <strong><span style="color: #993300;"> if key == ord("q"):</span></strong> <strong><span style="color: #993300;"> break</span></strong> <strong><span style="color: #993300;"># Dung camera</span></strong> <strong><span style="color: #993300;">vs.stop()</span></strong> <strong><span style="color: #993300;"># close all windows</span></strong> <strong><span style="color: #993300;">cv2.destroyAllWindows()</span></strong> |
Video hướng dẫn các setting giá tri HSV: