You are on page 1of 28

ĐẠI HỌC BÁCH KHOA HÀ NỘI

TRƯỜNG CƠ KHÍ

Khoa Cơ điện tử
***************

XỬ LÝ ẢNH
Đo kích thước vật thể realtime
Giảng viên hướng dẫn: TS. Dương Văn Lạc

Họ và tên Mã số sinh viên Lớp


Nguyễn Văn Đức 20194963 CĐT.01. K64
Đặng Đức Độ 20194948 CĐT.01. K64
Nguyễn Bá Công 20194926 CĐT.01. K64

HÀ NỘI, 7/2023

Đánh giá của giảng viên hướng dẫn


………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
2
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………………………………………………………………………
………………………

3
Kết quả đánh giá Hà Nội, ngày 31 tháng 7 năm 2023
Giảng viên hướng dẫn
Họ và tên Điểm
Nguyễn Văn Đức

Đặng Đức Độ

Nguyễn Bá Công

4
MỤC LỤC
CHƯƠNG 1. LỜI NÓI ĐẦU..................................................................................6

CHƯƠNG 2. TỔNG QUAN VỀ ĐỀ TÀI..............................................................7

2.1 Đề tài trong công nghiệp thực tế......................................................................7

2.2 Cơ sở lý thuyết cách đo kích thước vật thể bằng OpenCV thuần....................8

2.3 Phương án và các thức thực hiện.....................................................................9

CHƯƠNG 3. NỘI DUNG CÁC BƯỚC THỰC HIỆN.......................................11

3.1 Lấy ảnh...........................................................................................................11

3.1.1 Phương án sử dụng camera điện thoại...........................................11

3.1.2 Phương án xây dựng hệ đo realtime...............................................12

3.2 Tiền xử lý.......................................................................................................13

3.3 Đọc ảnh..........................................................................................................13

3.4 Chuẩn bị cho thuật toán Canny......................................................................14

3.5 Sử dụng thuật toán Canny..............................................................................15

3.6 Đo kích thước của vật....................................................................................16

3.6.1 Tìm đường bao vật thể...................................................................16

3.6.2 Diện tích hình chữ nhật tối thiểu bao quanh Contour....................17

3.6.3 Góc quay của hình chữ nhật tối thiểu.............................................18

3.6.4 Đo kích thước đường bao theo pixel..............................................20

3.6.5 Đo kích thước đường bao theo millimet........................................22

3.7 Xuất ảnh.........................................................................................................22

3.8 Realtime video...............................................................................................23

CHƯƠNG 4. KẾT LUẬN.....................................................................................24

5
4.1 Nhận xét và đánh giá......................................................................................24

4.2 Kết quả đạt được............................................................................................24

4.3 Những vấn đề khó khăn, chưa giải quyết được..............................................25

4.4 Hướng phát triển............................................................................................25

CHƯƠNG 5. TÀI LIỆU THAM KHẢO.............................................................26

6
CHƯƠNG 1. LỜI NÓI ĐẦU

Hiện nay, xử lý ảnh là một lĩnh vực đang được quan tâm rất nhiều. Tại hầu hết
các nước có nền khoa học tiên tiến trên thế giới, các loại trang thiết bị máy móc,
sản phẩm thông minh được ứng dụng hầu hết vào mọi lĩnh vực.
Trước đây, người ta thường chỉ sử dụng các thiết bị đo mà việc tính toán và xử lí
kết quả hoàn toàn là thủ công. Do những yêu cầu cấp thiết trong sản xuất chế tạo
mà đo lường ngày càng phát triển. Giờ đây với sự tiến bộ của các ngành cơ-điện
tử-tin học và việc ứng dụng những thành tựu của kỹ thuật điện tử, công nghệ thông
tin, trí tuệ nhân tạo, vào ngành cơ khí thì xử lí ảnh và đo lường trong các hệ thống
và robot công nghiệp đã được ứng dụng ngày càng rộng rãi. Nó là công cụ để
kiểm tra đánh giá chất lượng của sản phẩm, nó làm tai mắt cho các hệ thống tự
động hóa quá trình sản xuất hay các robot thông minh, với những khả năng vượt
trội so với các phương pháp truyển thống như:
 Khả năng tự xử lí và lưu trữ kết quả đo.
 Thực hiện công việc đo theo chương trình
 Tự động thu thập, phân loại và báo lỗi, …
Và trong lần này, nhóm chúng em làm với một đề tài nhỏ đó là đo kích
thước vật thể, với vật thể tham chiếu được chọn là đồng xu. Đề tài sử dụng thuật
toán Canny và thư viện Opencv.

7
CHƯƠNG 2. TỔNG QUAN VỀ ĐỀ TÀI

2.1 Đề tài trong công nghiệp thực tế

Sản phẩm sau khi được lắp ráp hay gia công đều cần được kiểm ngoại dạng
trước khi chuyển sang công đoạn tiếp theo để đảm bảo không để lọt bất cứ sản
phẩm lỗi hay kém chất lượng nào tới khách hàng. Thông thường công đoạn kiểm
tra này do người thao tác (công nhân) trực tiếp dùng mắt kiểm tra với 1 quy trình
nhất định. Việc này có nhiều ưu điểm song lại không đạt được độ chính xác cao
nhất mà nhà sản xuất mong muốn.
Từ những vấn đề đó, xử lý ảnh trong công nghiệp hiện nay phát triển có nhiều
ứng dụng có thể kể đến như:
 Nhận diện/kiểm tra ngoại dạng sản phẩm
 Nhận diện/kiểm tra màu sắc
 Đo lường/kiểm tra kích thước không tiếp xúc
 Kiểm tra kí tự quang học (OCV)
 Kiểm tra mã vạch
 Điều hướng Robot

Trong những ứng dụng trên, nhóm chúng em sẽ tập trung vào ứng dụng thứ
3 đó là đo lường và kiểm tra kích thước của vật. Các phép đo truyền thống được
thực hiện với các dụng cụ đo bằng cơ (đã được hiệu chỉnh rất chính xác) và người
thực hiện đo phải được huấn luyện về kĩ thuật đo mới đảm bảo kết quả đo có độ tin
cậy cao. Khi sản xuất hàng loạt, sản phẩm rất nhiều & nhỏ, khiến cho việc kiểm tra
kích thước sản phẩm bằng con người trở nên hết sức khó khăn và tốn kém vì vậy,
sự tiến bộ của kĩ thuật và công nghệ cung cấp giải pháp đo kiểm kích thước không
tiếp xúc dùng camera giúp xác định chính xác (cỡ dưới 10µm và bằng 10% dung
sai kích thước bản vẽ) với tốc độ cao các: khoảng cách, góc, diện tích, độ khớp
8
đường, độ khớp tròn … Từ đó nhà máy sẽ tiết kiệm được rất nhiều chi phí nhân
công, giảm được tối đa sai sót so với phương pháp đo kiểm truyền thống. Ứng
dụng này được xử dụng trong công nghiệp rất nhiều với nhiều những hình dạng và
kích thước khác nhau. Và trong lần này chúng em sẽ làm với đề tài đo kích thước
của một số vật đơn giản.

2.2 Cơ sở lý thuyết cách đo kích thước vật thể bằng OpenCV thuần

Muốn đo kích thước vật thể trong ảnh ta phải biết được các yếu tố như:
Khoảng cách từ camera đến vật khi chụp, Tiêu cự của camera, góc chụp…. rất
phức tạp như hình dưới:

Với một cách đơn giản hơn, ta sẽ hiểu như sau:


 Đầu tiên ta chọn một vật nào đó ta biết kích thước gọi là “Vật tham chiếu “.
Ta nên chọn một viên bi tròn hay vật gì đó hình tròn để dễ dàng hơn trong
việc tính toán. Giả sử viên bi có đường kính thật Dr =2 cm=20 mm.
 Tiếp theo ta đặt Vật tham chiếu đó vào ảnh cùng với các Vật muốn đo kích
thước và chụp một tấm.

9
 Sau đó, Giả sử ta đo được đường kính trong ảnh của Vật tham
chiếu là Dc =100 pixel, ta suy ra kích thước thật của 1-pixel là 20/100 =
0.2mm (goi là số P)
 Bước cuối cung, ta đo kích thước trong ảnh Vật muốn đo bằng pixel, sau đó
nhân với P là sẽ ra kích thước thật của vật.

2.3 Phương án và các thức thực hiện

Đo kích thước đồng xu qua xử lý ảnh có 2 cách chính:


 Đo khoảng cách từ camera đến nơi đặt đồng xu, góc nghiêng của camera so
với mặt phẳng chứa đồng xu, kết hợp với các thông tin về tiêu cự, vùng nhìn
(FOV) và góc nhìn (AOV) để tính toán ra được diện tích đồng xu.
 Nếu không sử dụng camera thì ta sẽ sử dụng mẫu chuẩn biết trước kích
thước, tính ra kích thước đồng xu theo tỉ lệ trên pixel. (Cách này cần mẫu
vật và đồng xu cùng nằm trong mặt phẳng FOV)
Nhóm sử dụng cách 2 để đo kích thước đồng xu.
Sau khi đo kích thước đồng xu làm vật tham chiếu, nhóm sẽ đo được kích thước
một số vật khác khi đặt vào cùng vị trí khung hình với lúc trước để nhân tỉ lệ theo
pixel đã quy đổi ra mm.
Các bước thực hiện:
Có thể chia quá trình làm 5 bước chính như sau:
 Bước 1 (Lấy ảnh): Thêm hình ảnh bằng cách sử dụng điện thoại đặt trên giá
cố định để đảm bảo hình ảnh vật mẫu và đồng xu cùng nằm trên một mặt
phẳng FOV.
 Bước 2 (Tiền xử lý): Ta lấy dữ liệu ảnh đã thu được và thực hiện các bước
tiền xử lý. Ở bước này ta sẽ dùng các hàm trong để đọc ảnh và điều chỉnh
kích thước của ảnh. Sau đó ta chuẩn bị cho thuật toán Canny bằng cách
chuyển sang ảnh xám và sử dụng bộ lọc Gauss để lọc nhiễu.
 Bước 3 (Đo kích thước của vật):

10
 (tìm đường bao): tìm cạnh của vật bằng thuật toán Canny và xử lí
đường bao bằng cách loại bỏ các đường viền nhỏ. Sau đó tính diện
tích của vật bằng định lý green.
 (đo kích thước): sau khi tìm được các contour ta thực hiện tính toán
kích thước của nó bằng cách tìm hình chữ nhật có diện tích bé nhất
của contour. Ta tính toán được chiều dài 2 cạnh theo pixel nhờ vào
các hàm trong thư viện OpenCV. Và cuối cùng ta tiến hành xử lý giá
trị chiều dài 2 cạnh theo pixel có ở trên để tìm được kích thước thật
bên ngoài
 Bước 4 (Xuất ảnh): Ảnh đã vẽ hình bao và ghi kích thước của đồng xu và
vật mẫu. Hoặc ở chế độ realtime, video xuất ra sẽ quay trực tiếp vật được đo
và ghi kích thước đo được lên khung hình camera.

11
CHƯƠNG 3. NỘI DUNG CÁC BƯỚC THỰC HIỆN

3.1 Lấy ảnh

3.1.1 Phương án sử dụng camera điện thoại

Nhóm sử dụng camera điện thoại để chụp được hình ảnh của vật cần đo. Để
đo được chính xác kích thước của vật, ta cần đảm bảo cố định hai yếu tố là góc
chụp của camera và khoảng cách từ camera tới vật. Do đó, điện thoại được gá cố
định trên một hệ khung như hình.

Hình 2.1 Cơ cấu chụp ảnh vật


Hệ khung trên giúp cho mặt phẳng của camera luôn song song với mặt
phẳng đặt vật. Ngoài ra, bên dưới mặt phẳng đặt vật có đèn led giúp loại bỏ bóng
của vật in xuống mặt phẳng, việc này giúp tạo ra các bức ảnh rõ nét và dễ dàng hơn
trong khi xử lý ảnh.

12
Hình 2.2 Hình ảnh của vật cần đo

3.1.2 Phương án xây dựng hệ đo realtime

Nhóm sử dụng các tấm fomex để làm thành hộp kín, có ánh sáng từ đèn điện
thoại, sau đó có chỗ để camera khác để thu hình ảnh vật đo đặt dưới đáy hộp.

Sau đây là hình ảnh thu được từ hệ:

13
3.2 Tiền xử lý

Khi có được các ảnh, trước hết ta lấy dữ liệu ảnh và thực hiện bước tiền xử lý.
Tất cả phần này được viết trong hàm:
image,edged = read_and_preprocess(filename, canny_low=50,
canny_high=100, blur_kernel=9, close_kernel=3)
với dữ liệu đầu vào gồm tên tệp ảnh (filename), ngưỡng thấp và cao của
thuật toán Canny (canny_low, canny_high), kích thước ma trận vuông cho nhân
của thuật toán làm mờ Gauss (blur_kernel), kích thước ma trận vuông cho nhân
của thuật toán hình thái học Closing (close_kernel). Đầu ra của hàm này là một ảnh
đọc từ tệp và một ảnh chứa cạnh của vật thể cùng nhiễu thông cao.0

3.3 Đọc ảnh

Nội dung hàm bắt đầu với hàm:


image = cv2.imread(filename, flag=none)

trong thư viện cv2. Trong đó, flag là cờ chuyển đổi kiểu dữ liệu ảnh. Hàm này sẽ
đọc từng điểm ảnh ở 3 kênh màu RGB, cho ra một mảng 3 chiều với 2 chiều đầu
tiên là kích thước ảnh, chiều thứ 3 là 3 kênh màu. Ở đây, ta bỏ qua flag để thu

14
được ảnh gốc. Do ảnh có độ phân giải cao, khi lấy dữ liệu sẽ cho ra ảnh lớn, nên ta
cần giảm kích thước ảnh mà không để ảnh sai tỉ lệ kích thước. Ta sẽ sử dụng hàm:
image = cv2.resize(src, dsize)

trong thư viện cv2. Src là ảnh gốc (image), dsize là kích thước mới của ảnh (siz1,
siz2). Kích thước mới được tính toán từ kích thước ảnh gốc, lấy được bằng đặc tính
của đối tượng ma trận - shape. Ta lấy kích thước ảnh gốc chia 1.5 cho đến khi kích
thước lớn nhất của ảnh nhỏ hơn 1000, sau đó chuyển kích thước về số nguyên.
Bước tính toán trên dưới dạng ngôn ngữ lập trình sẽ như sau:
siz1, siz2 = image. shape [0:2]
while max (siz1, siz2) > 1000:
siz1 = siz1/1.5
siz2 = siz2/1.5
siz1 = int(siz1)
siz2 = int(siz2)
image = cv2.resize(image, (siz2, siz1))

3.4 Chuẩn bị cho thuật toán Canny

Sau khi ảnh gốc đã đạt kích thước phù hợp, muốn thực hiện thuật toán tìm
cạnh Canny, ta cần chuyển ảnh sang ảnh xám để xử lý 1 kênh màu, làm mờ ảnh với
mặt nạ Gauss để xử lý nhiễu thông thấp mà cạnh của vật thể không bị biến dạng
quá nhiều. Ta chuyển ảnh sang ảnh xám với hàm:
gray = cv2.cvtColor(src, code)

trong thư viện cv2. Src là ảnh gốc (image), code là gọi hàm chuyển đổi không gian
màu (cv2.COLOR_BGR2GRAY). Hàm này lấy giá trị trung bình của 3 kênh màu tại mỗi
pixel, ta sẽ thu được ảnh 1 kênh màu (ảnh xám) ở đầu ra. Sau đó, ta sử dụng hàm:
blur = cv2.GaussianBlur(src, ksize, sigmaX)

trong thư viện cv2. Với src là ảnh gốc (gray), ksize là kích thước mặt nạ Gauss
(blur_kernel, blur_kernel), sigmaX là hệ số trong đồ thị phân bố xác suất chuẩn
Gauss theo trục x (để bằng 0, vì đã chọn ksize nên không cần). Hàm này sử dụng

15
mặt nạ phân bố chuẩn Gauss, thực hiện tích chập với ảnh gốc. Đầu ra của hàm này
là ảnh được làm mờ.

3.5 Sử dụng thuật toán Canny

Tiếp theo, ta sử dụng thuật toán Canny để tìm cạnh với hàm:
edged = cv2.Canny(image, threshold1, threshold2)

trong thư viện cv2. Image là ảnh gốc (blur), threshold1 là ngưỡng thấp
(canny_low), threshold2 là ngưỡng cao (canny_high). Thuật toán Canny thực hiện
tích chập ảnh với mặt nạ Sobel để tìm các vector vuông góc với cạnh, loại bỏ các
điểm không phải cực đại địa phương (đưa về 0), sau đó dùng ngưỡng để chọn ra
thành phần cạnh và không phải cạnh. Cụ thể, tích chập với ma trận Sobel có dạng
như sau:

Trong đó, A là ma trận dữ liệu ảnh, (G x, Gy) là vector hướng G tại từng
điểm. Vector G có hướng luôn vuông góc với các đường cạnh trong ảnh (ranh giới
nơi cường độ sáng có bước nhảy), có độ dài tỉ lệ với độ chênh lệch cường độ sáng
với các điểm ảnh lân cận. Từ giá trị độ dài của G, ta lọc cơ sở bằng cách giữ lại các
điểm là cực đại so với 2 điểm lân cận (xét trên 4 phương), các điểm khác đưa về
giá trị 0.
Khi có được các điểm ảnh có khả năng là cạnh, ta áp đặt ngưỡng cao và
ngưỡng thấp để giữ lại các cạnh đủ lớn. Các điểm ảnh có (|G| > ngưỡng cao) hoặc
(|G| > ngưỡng thấp và nằm cạnh điểm ảnh có |G| > ngưỡng cao) sẽ được giữ lại.
Đầu ra của hàm là ảnh nền đen cạnh trắng.
Để đề phòng trường hợp cạnh bị đứt đoạn nhỏ, ta sử dụng thuật toán Closing
gồm 2 hàm:
edged = cv2.dilate(src, kernel)

16
edged = cv2.erode(src, kernel)
trong thư viện cv2. Src là ảnh gốc (edged), kernel là ma trận dùng tích chập với
ảnh (có thể chỉ cần đưa vào kích thước (close_kernel, close_kernel)). Dilate
và erode sẽ tích chập mặt nạ với ảnh, dilate đặt điểm mốc giá trị 255 khi và chỉ khi
ít nhất một điểm qua mặt nạ khác 0, còn erode thì đặt điểm mốc giá trị 255 khi và
chỉ khi tất cả điểm qua mặt nạ đều khác 0. Kết quả là dilate làm phần màu trắng
giãn ra, cạnh bị đứt sẽ được nối liền, erode làm phần màu trắng co lại kích thước
ban đầu. Như vậy là đã kết thúc bước tiền xử lý.

3.6 Đo kích thước của vật

3.6.1 Tìm đường bao vật thể

Sau bước tiền xử lý – sử dụng thuật toán Canny detection để tìm ra cạnh,
đường viền của bức ảnh ta sử dụng thuật toán FindContour để tìm đường viền
mong muốn dưới dạng là chuỗi tọa độ các điểm trên đường viền (bao gồm tất cả
các đường viền và cạnh bao):
cnts=cv2.findContours(edged.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_
SIMPLE)
Ở đây ta điền 3 tham số:
 edged.copy() – đây là tham số ảnh sau khi đã tiền xử lý sử dụng Canny
Detection, như trong code là ảnh copy từ ảnh edge đã được xử lý ở trên.
 cv2.RETR_EXTERNAL – đây là tham số giúp chúng ta chỉ lấy các đường viền
bên ngoài, loại bỏ các đường viền bên trong.
 cv2.CHAIN_APPROX_SIMPLE – tham số này sẽ loại bỏ các nét thừa, đường
viền không kín.
Kết quả chúng ta sẽ được tập hợp các tọa độ thuộc các đường bao.
Sau đó ta tiến hành đưa các chuỗi tìm được về dạng dữ liệu Tuple (sử dụng
hàm imutils.grab_contours()) trong python để xử lý các đường viền này :
cnts = imutils.grab_contours(cnts)

17
Tham số đưa vào là ‘cnts’ đây là kết quả lấy được từ hàm findcontour,
qua hàm trên sẽ chuyển tạp hợp các tọa độ về dạng dữ liệu Tuple (nhóm các tạo độ
cùng thuộc 1 đường bao)
Tiếp theo ta tiến hành sắp xếp các đường viền theo thứ tự từ trái qua phải
trên dữ liệu vừa nhận được qua hàm:
(cnts, _) = contours.sort_contours(cnts)
Ta loải bỏ các đường viền nhỏ (không cần thiết) trên ảnh mà ta thu được
thông qua việc so sánh diện tích của các đường bao (sử dụng hàm contourArea()
để tìm diện tích của các đường bao) với một số xác định đã được cho trước:
if cv2.contourArea(c) < area_threshold :
continue
Ở đây c chính là tập hợp các tọa độ pixel thuộc cùng một đường bao đã xác
định ở trên, area_threshold là giá trị giới hạn diện tích theo pixel mà nếu nhỏ
hơn ta sẽ loại bỏ. Từ đầu vào của thuật toán contourArea( ) là tập hợp tọa độ các
pixel thuộc cùng một đường bao, ta sẽ vẽ được dạng của đường bao. Sau đó áp
dụng định lý Green ta sẽ tính được diện tích của đường bao theo đơn vị là pixel

Ở đây ta có công thức diện tích theo định lý Green:

18
3.6.2 Diện tích hình chữ nhật tối thiểu bao quanh Contour

Hình ảnh bên dưới hiển thị 2 hình chữ nhật, hình chữ nhật màu xanh lá cây
là hình chữ nhật bao quanh bình thường trong khi hình màu đỏ là hình chữ nhật có
diện tích tối thiểu. Xem cách xoay hình chữ nhật màu đỏ.

Hình: Box chữ nhật bao quanh contour


OpenCV cung cấp một hàm cv2.minAreaRect() để tìm diện tích nhỏ nhất
được xoay hình chữ nhật. Điều này lấy đầu vào là tập hợp điểm 2D và trả về cấu
trúc Box2D chứa các chi tiết sau – (tâm (x, y), (chiều rộng, chiều cao), góc
quay). Cú pháp được đưa ra dưới đây:
(Center (x, y), (width, height), angle of rotation) = cv2.minAreaRect(points)
Nhưng để vẽ một hình chữ nhật, chúng ta cần 4 góc của hình chữ nhật. Vì
vậy, để chuyển cấu trúc Box2D thành 4 điểm góc, OpenCV cung cấp một chức
năng khác là cv2.boxPoints(). Cái này lấy cấu trúc Box2D làm đầu vào và trả về 4
điểm góc. 4 điểm góc được sắp xếp theo chiều kim đồng hồ bắt đầu từ điểm có y
cao nhất. Cú pháp được đưa ra dưới đây:
points = cv2.boxPoints(box)

19
3.6.3 Góc quay của hình chữ nhật tối thiểu

Như chúng ta đã biết rằng 4 điểm góc được sắp xếp theo chiều kim đồng hồ
bắt đầu từ điểm có y cao nhất như hình bên dưới. Nếu 2 điểm có cùng y cao nhất
thì điểm ngoài cùng bên phải là điểm xuất phát. Các điểm được đánh số là 0,1,2,3
(0-bắt đầu, 3-kết thúc).

Vì vậy, góc quay được cung cấp bởi cv2.minAreaRect() của OpenCV thực
sự là góc giữa đường thẳng (nối điểm đầu và điểm cuối) và phương nằm ngang
như minh họa bên dưới:

Do đó, giá trị góc luôn nằm trong khoảng [-90,0) . Tại sao? bởi vì nếu vật thể
bị xoay hơn 90 độ, thì cạnh tiếp theo được sử dụng để tính góc so với phương
ngang. Và do đó, góc được tính toán luôn nằm trong khoảng [-90,0). Xem hình ảnh
bên dưới trong đó đường màu xanh lá cây hiển thị đường nối điểm đầu và điểm

20
cuối được sử dụng để tính góc. Ngoài ra, hãy xem điểm bắt đầu và điểm cuối thay
đổi như thế nào khi xoay đối tượng. Các điểm được đánh số là 0,1,2,3 (0-bắt đầu,
3-kết thúc).

3.6.4 Đo kích thước đường bao theo pixel

Sau khi tìm được các contour, ta sẽ thực hiện tính toán kích thước của nó
bằng pixel. Ở đây ta sẽ đo kích thước của vật bằng cách tìm MinAreaRect, tức là
hình chữ nhật bao có diện tích bé nhất của contour, xác định vị trí các đỉnh và tính
độ dài 2 chiều của hình chữ nhật này theo pixel và mm.
Ta định nghĩa hàm get_distance_in_pixels (orig, c) nhận vào 2 biến là
ảnh gốc và contour c đã tìm được:
def get_distance_in_pixels (orig, c):
box = cv2.minAreaRect(c)
box = cv2.boxPoints(box)
box = np. array (box, dtype="int")
Hàm minAreaRect () của opencv cho kết quả là tọa độ điểm trên cùng bên
trái, chiều dài, chiều rộng, góc xoay của hình chữ nhật bao bé nhất của contour c.
Sau đó ta đưa vào hàm boxPoints () của opencv để từ các dữ liệu trên, tính ra tọa
độ 4 đỉnh của hình chữ nhật. Sau đó ta đưa vào array () của numpy để chuyển các
tọa độ thành mảng kiểu int.
# Sắp xếp các điểm theo trình tự
box = perspective. order_points(box)
cv2.drawContours(orig, [box. astype("int")], -1, (0,255,0), 2)
Do các điểm góc của hình chữ nhật bao bị xoay, ta dùng hàm order_points
() của thư viện imutils. perspective để sắp xếp các tọa độ theo thứ tự cùng chiều
kim đồng hồ, bắt đầu từ điểm trên cùng bên trái. Sau đó ta vẽ contour.
(tl, tr, br, bl) = box
(tltrX, tltrY) = midpoint(tl, tr)
(blbrX, blbrY) = midpoint(bl, br)
(tlblX, tlblY) = midpoint(tl, bl)

21
(trbrX, trbrY) = midpoint(tr, br)
Sau đó, ta tìm tọa độ trung điểm các cạnh bằng hàm midpoint().
dc_W = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
dc_H = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))

Sau đó, ta sử dụng hàm euclidean() từ thư viện scipy.spatial.distance để


tính khoảng cách. Hàm nhận vào 2 mảng 1 chiều có cùng số phần tử là tọa độ các
trung điểm đối nhau và trả về giá trị là khoảng cách Euclid của 2 điểm đó. Từ đó ta
có độ dài 2 chiều của hình chữ nhật minAreaRect.
return dc_W, dc_H, tltrX, tltrY, trbrX, trbrY

Kết thúc hàm get_distance_in_pixels(orig, c), ta trả về giá trị độ dài 2


chiều của minAreaRect, cũng là độ dài kích thước của contour c bằng pixel, và
trung điểm của 4 cạnh minAreaRect bao contour c.
Để sử dụng hàm midpoint(), ta cần định nghĩa hàm:
def midpoint(ptA, ptB):
return ((ptA[0] + ptB[0])/2, (ptA[1] + ptB[1])/2)
Thuật toán tìm diện tích hình chữ nhật nhỏ nhất cv2.minAreaRect(c):
Dựa vào định lý là hình chữ nhật bao nhỏ nhất của một đa giác lồi luôn có
một cạnh trùng với một cạnh của đa giác đó. Ta đã có contour c là một tập điểm, ta
xây dựng nó thành 1 đa giác lồi.
Với mỗi cạnh của đa giác, tính góc của nó so với trục hoành.
 Xoay hình theo góc để 1 cạnh song song vs trục hoành.
 Lập hình chữ nhật bao (lấy các điểm min/max bên trái, phải, trên, dưới và
lập hcn có các cạnh // với trục tung và trục hoành), ta có 1 cạnh của hcn
trùng với cạnh / trục hoành. Tính diện tích của hcn này.
 Lặp lại với n-1 cạnh còn lại. Xác định diện tích bé nhất.
Xuất ra góc tương ứng và tọa độ điểm trên cùng bên trái, cùng độ dài 2 chiều.
Thuật toán lấy các điểm góc của hình chữ nhật cv2.boxPoints(box):
 Từ độ dài 2 chiều và góc xoay tính dx, dy của các điểm so với điểm top-left,
sau đó cộng vào tọa độ điểm top-left để ra các điểm còn lại.
22
Thuật toán sắp xếp các điểm theo trình tự perspective. order_points(box):
 Sắp xếp các điểm theo thứ tự tăng dần của tọa độ x, sau đó lấy 2 điểm có tọa
độ x nhỏ hơn là 2 điểm bên trái.
 Từ 2 điểm này, chọn điểm có tọa độ y lớn hơn là điểm trên. Điểm còn lại là
điểm dưới.
 Tính khoảng cách Euclid giữa điểm trên cùng bên trái và 2 điểm còn lại.
Điểm nào xa hơn là điểm dưới cùng bên phải.
Thuật toán tính độ dài distance.euclidean((xa, ya, za…), (xb, yb, zb…) ):
sqrt((xa-xb)^2+ (ya-yb)^2+ (za-zb)^2+….)

3.6.5 Đo kích thước đường bao theo millimet

Cuối cùng ta tiến hành xử lý giá trị chiều dài 2 cạnh theo pixel có ở trên để
tìm được kích thước thật bên ngoài:
if P is None:
P = ref_wi
.dth / dc_H
dr_W = ref_width
dr_H = ref_width
else:
dr_W = dc_W * P
dr_H = dc_H * P
Cuối cùng ta xác định P – chiều dài 1-pixel tính theo đơn vị mm, với
ref_width là chiều dài vật tham chiếu được cho trước, dc_H là chiều dài vật tham

chiếu tính theo pixel. Và sau khi có được P ta tiến hành xác định chiều dài cần tìm
bằng các nhân P với chiều dài tính theo đơn vị pixel cảu vật cần xác định. (Việc
tìm P được tính lần đầu tiên khi chưa có số liệu của P, khi đã biết P ta chỉ đi tìm
chiều dài thực với P đã có)

3.7 Xuất ảnh

23
Để xuất ảnh, ta dùng hàm cv2.imshow(winname, mat) trong thư viện cv2,
trong đó, winname là tên cửa sổ mở ra, mat là ma trận dữ liệu ảnh. Vì thực thi
xong chương trình sẽ đóng lại nên cần hàm cv2.waitKey() trong thư viện cv2 để
hệ thống chờ cho người dùng nhấn 1 nút bất kì từ bàn phím.

3.8 Realtime video

cap = cv2.VideoCapture(1)
if not cap.isOpened():
print("cannot open camera")
exit()
while True:
# Capture frame by frame
ret,frame = cap.read()
# if frame is read corectly ret is true
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break

image, edged = read_and_preproces(frame)


image = find_object_in_pix(image, edged)
scale = 150 # percent of original size
width = int(image.shape[1] * scale / 100)
height = int(image.shape[0] * scale / 100)
dim = (width, height)
image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
cv2.imshow("A", image)
if cv2.waitKey(1) == ord('q'):
break
# When everything done, release the capture
24
cap.release()
cv2.destroyAllWindows()

CHƯƠNG 4. KẾT LUẬN

4.1 Nhận xét và đánh giá

Từ cơ sở lý thuyết và thực hành trên ta có một số nhận xét và đánh giá thuật toán
Canny Edge Detection với một số trường hợp ảnh sau:
- Đối với ảnh không nhiễu: Do quá trình làm trơn ảnh nên từ một ảnhkhông
nhiễu các biên mờ bớt đi và to ra. Do vậy, biên ảnh trong phương pháp Canny lớn
nhưng lại không đầy đủ, không nên áp dụng.
- Đối với ảnh có nhiều cạnh: Khi phát hiện biên các cạnh không quan trọng
nên được loại bỏ. Do quá trình “Non - maximum Suppression” và do quá trình áp
dụng ngưỡng mà các điểm biên phụ bị loại bớt đi, các biên chính được giữ lại nên
biên rõ nét hơn.
- Đối với ảnh có nhiều nhiễu: Do quá trình làm trơn ảnh cho bớt nhiễu và quá
trình “Non – maximum Suppression” giảm bớt các biên phụ nên ảnh kết quả của
phương pháp này rất rõ nét. Vì vậy phương pháp này rất thích hợp cho loại ảnh
này.

4.2 Kết quả đạt được

25
Hình 3.1 Kích thước của vật đo được
 Tìm hiểu và nắm rõ được thuật toán Canny Edge Detection
 Biết về thuật toán Find Coutour
 Phân biết, nắm rõ một số thuật ngữ trong xử lý ảnh
 Sử dụng OpenCv để thực hiện xử lý một bức ảnh
 Trau dồi thêm kiến thức mới.

4.3 Những vấn đề khó khăn, chưa giải quyết được

 Mất nhiều thời gian sửa lỗi trong quá trình thực hiện
 Project còn đơn giản

4.4 Hướng phát triển

Ngoài việc đo kích thước những vật đơn giản, nhóm sẽ tiếp tục triển khai
nghiên cứu đề tài lớn hơn là đo kích thước bàn tay, ứng dụng trong nhà máy sản
xuất gang tay.

26
CHƯƠNG 5. TÀI LIỆU THAM KHẢO

 Giáo trình xử lý ảnh, Học viện Bưu chính Viễn thông


 Thomas Klinger, Image Processing with LabVIEW and IMAQ Vision, 2003
 Bernd Jähne, Digital Image Processing, 2002
 https://minhng.info/tutorials/xu-ly-anh-opencv-hien-thuc-canny-edge.html
 https://www.miai.vn/2020/07/21/do-kich-thuoc-vat-the-bang-opencv-thuan/?
fbclid=IwAR3IR9ZztN-Dki-
EcB1EUOuVQAEi9UeE9e1wlk5wSzJ4P5Jd09nYyotc1K0

27
28

You might also like