Lập trình hiệu ứng ChromaKey với Visual C++ sử dụng OpenCV


(Chien CG) #1

Chào mọi người, mình mới tham gia diễn đàn vì mới được biết từ forum daynhauhoc.com, đây là bài viết đầu tiên của mình, không biết có đặt đúng nơi, đúng chỗ không, có vấn đề gì mong được mọi người nhắc nhở :smile:

Như tiêu đề đã viết, chắc có nhiều người trong diễn đàn mình quen hoặc đã biết qua thuật ngữ Chroma key(CK) rồi, tuy nhiên hầu hết các chương trình edit video, biên tập… hiện nay như Adobe After Effects, Premiere đều chỉ cho phép thực hiện key offline, tức là thực hiện key xong toàn bộ mới có thể phát video, trong khi đó mình tìm trên mạng các phần mềm có hỗ trợ key real time (như là chương trình trực tiếp) thì lại có phí, thậm chí là phí rất cao.
Xuất phát từ những điều trên, mình đang tìm hiểu và xây dựng chương trình key real time bằng Visual C++ sử dụng OpenCV, tuy nhiên đây không phải công việc dễ dàng vì kiến thức C++ của mình còn hạn chế, và nguồn tài liệu trên mạng không có nhiều. Kết quả mình có được hiện nay là đã key được cho phông xanh không bị chặn chia cắt, nhưng trong trường hợp bị chặn chia cắt thì mình không biết làm sao để nó key được nữa!
Không biết trong diễn đàn mình có ai đã, đang hoặc có hứng thú với chủ đề này thì cho mình ý kiến, hoặc tốt hơn là tham gia làm cùng mình không ạ? :smile:
Đây thực sự là một đề tài rất hay và có ứng dụng lớn, mong mọi người nhiệt tình ý kiến ạ :smile:


(Nguyễn Mạnh Hà) #2

Diễn đàn chưa có nhiều người sử dụng Video editor, vfx. Hy vọng sẽ có nhiều đóng góp về chuyên mục này. Cảm ơn bài viết của bạn :smiley:


(Chien CG) #3

Em chính là đọc được đoạn anh nói chuyện vs a Đạt bên DNH mới biết ở đây mà tìm đến, có lẽ đây là đất của CG Programming rồi, em cũng hy vọng có nhiều cao nhân xuất hiện tham gia bình loạn (luận) hơn nữa :smile:


(Nguyễn Mạnh Hà) #4

A cũng rất thích CG Programming nhưng không có thời gian để cày, tuy nhiên tương lai muốn phát triển hơn nữa thì phải đầu tư vào nó. E đón đầu trước là rất khôn ngoan đấy :smile:


(Chien CG) #5

Anh nói rất chuẩn, nhưng vì nó là “tương lai” nên không nói trước được và khó quá anh ạ, ít người để trao đổi, ít chỗ để học hỏi anh ạ :smile:


(Tuan Nguyen) #6

Bạn chịu khó lên mạng search thêm tài liệu về realtime green screen algorithm
về phương pháp mà họ tách mầu, hoặc sample code rồi cứ test dần dần thôi.

Để điều để ra được sản phẩm cuối cùng sẽ mất nhiều thời gian và công sức lắm đấy :wink:

http://people.unica.it/riccardoscateni/files/2014/09/Corda2014CAC.pdf


(Chien CG) #7

Cảm ơn bạn @illunara nhiều, mình vẫn đang trong quá trình nghiên cứu về vấn đề này, nhưng đơn thương độc mã cũng có nhiều hạn chế, nếu bạn có hứng thú chúng ta cùng tìm hiểu xem sao? :blush:
Cũng không còn cách nào khác ngoài cách bạn nói :smile:, tuy nhiên bài báo bạn đưa lên quả thực rất có ích, mình sẽ thử xem sao :smiley:


(Tuan Nguyen) #8

Mình là animation td nên ko có kiến thức về VFX cũng như phân tích điểm ảnh. Nếu bạn có quen ai làm trong FPT, trong đấy có rất nhiều người làm về mảng này, dù họ dùng C là chính, nhưng kiến thức cơ bản thì vẫn có thể hỏi được :wink:


(Animation Apprentice) #9

nếu như dùng Visual C++ mình nghĩ là ko thể chạy trên linux và mac đc, bạn nên hướng tới đa nền tảng, nhất là nếu như bạn muốn làm một dự án free/mã nguồn mở

phương pháp chính vẫn là duyệt qua từng frame của video, xét xem pixel nào là phông nền thì sẽ sửa màu của nó thành alpha để trở nên trong suốt, không phải là phông nền thì để nguyên (về xét pixel bạn có thể tìm hiểu lý thuyết Alpha Compositing)
bạn chỉ cần key được phông xanh của một image ra thì chắc chắn sẽ chạy được với video là xử lý real-time, bởi chúng cũng là các image sequence

chuyên môn của mình là CNTT và mình cũng rất muốn tham gia cùng, nhưng hiện tại mình rất hạn chế về thời gian, nên chắc mình xin ngồi hóng + chém gió phụ :smile:


(Animation Apprentice) #10

về link PDF mà bạn ở trên đăng thì người ta dùng một phương pháp khác với xử lý từng pixel, đó là color keying mà OpenGL đã xây dựng sẵn, bản chất của việc này là tất cả các màu mà bạn chọn nó là key thì lúc render sẽ trở nên trong suốt (việc khó là xác định đúng màu, ko đc lẫn sang các màu khác vì trong tự nhiên biến thiên các màu rất mạnh) phương pháp này ưu điểm là dễ thực thi, không yêu cầu phần cứng cao (nếu bạn dùng OpenCV thì CPU phải khỏe), OpenGL chạy trên các GPU và xử lý cực kỳ nhanh.
Chắc bạn nên thử nghiệm và kiểm tra các phương pháp và lựa chọn ra cái phù hợp


(Chien CG) #11

Hãy khoan nói về các thứ khác, mình xin phép được show ra những gì mình đang làm được ở link dưới đây:

  • Xin được giải thích 1 chút: mình đã có thể key thành công trong trường hợp không có vật chắn (ở đây là hình màu đen che trước màn hình trong video), hoặc vật chắn không chia cắt màn hình (font xanh). Trường hợp trong video là vật chắn chia cắt màn hình, dẫn tới tình trạng không key được hoàn toàn.

  • Thuật toán chung của mình như sau: xác định 4 điểm góc của font xanh rồi thực hiện key theo tọa độ 4 điểm đó, theo đó, khi không có vật đen chia cắt màn hình, dựa vào các pixel xanh liền nhau, ta có thể xác định được tọa độ 4 điểm đó và key được dễ dàng. Tuy nhiên khi có vật chắn chia cắt màn hình, ta không xác định được chính xác 4 điểm trên vì để xác định được chính xác, cần các pixel xanh liên tục.

  • Khắc phục: Mình đã tìm được cách khắc phục bằng cách lưu 1 trạng thái chuẩn(1) (trạng thái không bị chia cắt) của font xanh vào và key theo trạng thái đó(2), trong trường hợp bị chia cắt(3) sẽ cộng dồn trạng thái đã được key(2) trên vào trạng thái bị chia cắt(3) để ra được trạng thái cuối cùng là như trong video (4), ở trạng thái này màu xanh của trạng thái (3) chưa bị khử và công việc bây giờ là khử nó để nó trở thành trong suốt đối với trạng thái (2).

Xin mọi người cho ý kiến :smile:


(Animation Apprentice) #12

nếu theo như mình hiểu thì luôn phải xác định vùng của phông xanh cho cảnh quay đó, khi chuyển cảnh thì có cần phải cập nhật một số giá trị hay ko? nếu vật chắn có hình dạng khác thì liệu có bị ảnh hưởng? mình nghĩ là còn một vấn đề nữa là màu xanh trong những cảnh quay video thật thì nó không hẳn là xanh mà các pixel sẽ xanh nhiều màu khác nhau, mong là bạn không dùng cách đối chiếu màu xanh để tìm ra pixel cần cho thành trong suốt :smile:


(Chien CG) #13

Hiện tại mình đang thử với góc quay là cố định đã, tức là vùng font xanh coi như cố định, ngay cả trong trường hợp vùng font xanh không cố định mà vùng đó không bị chia cắt, mình cũng key được ok rồi :smile:

Mình đã thử đủ các kiểu, có test cả trường hợp người đứng trước font xanh mà không bị chia cắt thì việc key vẫn thành công!

Đúng là các pixel sẽ bị khác nhau vì thông thường còn có đổ bóng , tuy nhiên việc này khắc phục được bằng cách dùng hệ thống đèn sao cho người đừng trước font không bị đổ bóng lên font, trường hợp này camera cố định nữa nên coi như màu xanh là không đổi, ngay cả trong trường hợp camera di chuyển thì mình nghĩ cũng không phải vấn đề vì ta có thể nới rộng ngưỡng xanh ra khi chuyển sang ảnh xám.
Vấn đề duy nhất còn lại mình đang mắc là không biết làm sao để loại bỏ màu xanh ở ảnh chia cắt, vì thuật toán của mình là xác định các điểm góc dựa vào sự liên tục của màu xanh, mình cũng đã thử làm cho màu xanh thành trong suốt bằng cách đưa về ảnh mức xám, cứ cho là lí tưởng đi thì các pixel xanh về 0 hết (màu trắng), nhưng khi cộng vào thì chương trình không lỗi nhưng lại vướng exception, chả hiểu, rõ là cộng 2 ma trận cùng kích thước. Đang bị mắc ở đó :smile:, dùng phép cộng, and hay or đều có vấn đề, có lẽ với ảnh chia cắt lại phải tìm thuật toán key khác!


(Chien CG) #14

Báo với mọi người là mình đã key thành công rồi nhé, anh em nào quan tâm thì trao đổi để phát triển thêm :smile:
Video thành phầm: https://youtu.be/SLFUJYz5PBk


(Nguyễn Lê Hà) #15

Cái background animate bạn là người design đấy à?


(Chien CG) #16

Dạ vâng, em làm để test anh ạ :smile:


(Nguyễn Duy Dũng) #17

Chủ thớt thử tham khảo XSplit hay Open Broadcaster (Open Source) xem. Đây 2 chương trình hỗ trợ stream, cũng có khả năng Chroma Key realtime đó


(Chien CG) #18

Cảm ơn bạn, mình sẽ thử tìm hiểu về cái bạn nói xem sao, nếu có rồi thì tốt quá vì bài toán này vẫn còn rất nhiều viêc phải làm :smile: