OpenCV rất mạnh, nhưng mỗi script đều phải lặp lại cùng một nhóm thao tác:
image = cv2.imread(path) # imread trả None nếu lỗi — không có exception
if image is None: # phải tự kiểm tra mỗi lần
print("Error")
return
# ... xử lý ...
cv2.imwrite(output, result) # cũng trả False im lặng nếu lỗi
cv2.imshow("title", result)
cv2.waitKey(0)
cv2.destroyAllWindows() # giết hết cửa sổ, kể cả không phải của mìnhcvkit chỉ wrap những phần lặp thật sự — phần còn lại gọi OpenCV gốc.
Chỉ wrap khi tiết kiệm được boilerplate thật sự. Nếu OpenCV gốc đã là 1 dòng dễ đọc → gọi trực tiếp, không wrap.
| Có trong cvkit | Lý do |
|---|---|
load_image |
5 bước: resolve path → check tồn tại → imread → phân biệt FileNotFoundError vs decode error |
save_image |
5 bước: validate image → check extension → mkdir -p → imwrite → trả Path |
show_image |
try/finally lifecycle — chỉ đóng đúng cửa sổ mình tạo |
translate_image |
2 bước: build affine matrix + warpAffine — dễ viết sai matrix |
to_binary |
cv2.threshold trả tuple (retval, image) — phải unpack _ mỗi lần |
draw_polygon |
3 bước: np.array → .reshape((-1,1,2)) → cv2.polylines — reshape dễ sai |
preview_usb_camera |
open → loop → try/finally release — quản lý lifecycle thiết bị |
preview_csi_camera |
lazy import + init + loop + safe release — lifecycle + error handling |
| KHÔNG có trong cvkit | Lý do |
|---|---|
cv2.resize(img, size) |
1 dòng, đủ rõ |
cv2.flip(img, code) |
1 dòng, đủ rõ |
cv2.cvtColor(img, BGR2GRAY) |
1 dòng, đủ rõ |
cv2.Canny(img, t1, t2) |
1 dòng, đủ rõ |
cv2.line, rectangle, circle, ellipse, putText |
Mỗi cái 1 dòng, wrap chỉ tạo thêm layer |
cvkit/
├── __init__.py ← public API (8 hàm)
├── io.py ← load / save / show + ImageIOError
├── ops.py ← translate_image, to_binary
├── draw.py ← draw_polygon
└── camera.py ← preview_usb_camera, preview_csi_camera
from pathlib import Path
import cv2
from cvkit import load_image, save_image, show_image
BASE_DIR = Path(__file__).resolve().parent
def main() -> None:
image = load_image(BASE_DIR / "images" / "photo.png")
# Gọi OpenCV gốc cho thao tác 1 dòng
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)
save_image(BASE_DIR / "images" / "edges.png", edges)
show_image("Edges", edges)
if __name__ == "__main__":
main()from cvkit import preview_usb_camera
def detect_and_draw(frame):
# chạy detection, vẽ overlay...
cv2.putText(frame, "LIVE", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
return frame
preview_usb_camera(on_frame=detect_and_draw)Copy thư mục cvkit/ vào project, hoặc thêm parent path:
import sys
sys.path.insert(0, "/path/to/01. openCV")
from cvkit import load_imageThêm hàm mới vào cvkit chỉ khi:
- Hàm đó kết hợp ≥2 bước OpenCV, hoặc
- Return value của OpenCV cần xử lý (unpack, reshape...), hoặc
- Cần quản lý lifecycle (open/close, try/finally)
Nếu chỉ là 1 dòng gọi OpenCV — đừng wrap, gọi trực tiếp.