Xử lý ảnh OpenCV

Xu Ly Anh Opencv



Chúng ta sẽ nghiên cứu các phương pháp xử lý ảnh trong bài viết này. Chúng ta sẽ xem xét một số chủ đề cơ bản nhưng quan trọng trong thị giác máy tính và học máy. Những kỹ thuật xử lý hình ảnh cơ bản này có thể giải quyết các vấn đề phức tạp, chẳng hạn như bộ dữ liệu. Kết quả là, có sáu bước cơ bản trong xử lý ảnh, được liệt kê dưới đây:
  1. Dịch hình ảnh
  2. Xoay hình ảnh
  3. Số học hình ảnh
  4. Lật ảnh
  5. Cắt ảnh
  6. Thay đổi kích thước hình ảnh

Bây giờ, chúng tôi sẽ giải thích chi tiết tất cả các chủ đề xử lý hình ảnh nêu trên.

1. Dịch hình ảnh

Dịch ảnh là phương pháp xử lý ảnh giúp chúng ta di chuyển ảnh theo trục x, y. Chúng ta có thể di chuyển hình ảnh lên, xuống, phải, trái hoặc bất kỳ sự kết hợp nào.







Chúng ta có thể định nghĩa Ma trận dịch bằng ký hiệu M và chúng ta có thể biểu diễn nó dưới dạng toán học, như hình dưới đây:





Chúng ta có thể hiểu khái niệm về hình ảnh dịch thông qua chương trình này.





Mã trăn: Chúng tôi sẽ giữ tên chương trình sau đây như dịch.py .

# nhập các gói cần thiết

nhập khẩu cục mịch như ví dụ.

nhập khẩu argparse

nhập khẩu không sử dụng được

nhập khẩu cv2

# chúng tôi triển khai trình phân tích cú pháp đối số

ap_obj = argparse. Đối sốParser ( )

ap_obj. add_argument ( '-k' , '--hình ảnh' , cần thiết = Thật ,

Cứu giúp = 'vị trí của tập tin hình ảnh' )

tranh luận = của ai ( ap_obj. parse_args ( ) )

# tải hình ảnh và hiển thị trên màn hình

hình ảnh = cv2. imread ( tranh luận [ 'hình ảnh' ] )

cv2. hiển thị ( 'Ảnh gốc' , hình ảnh )

# Bản dịch của hình ảnh là ma trận NumPy được đưa ra bên dưới:

# [[1, 0, shiftX], [0, 1, shiftY]]

# Chúng ta sẽ sử dụng ma trận NumPy ở trên để dịch chuyển hình ảnh dọc theo

# hướng trục x và trục y. Đối với điều này, chúng ta chỉ cần chuyển các giá trị pixel.

# Trong chương trình này, chúng tôi sẽ di chuyển hình ảnh 30 pixel sang bên phải

# và 70 pixel về phía dưới.

dịch_mat = ví dụ. phao32 ( [ [ 1 , 0 , 30 ] , [ 0 , 1 , 70 ] ] )

image_translation = cv2. cong vênh Affine ( hình ảnh , dịch_mat ,

( hình ảnh. hình dạng [ 1 ] , hình ảnh. hình dạng [ 0 ] ) )

cv2. hiển thị ( 'Dịch hình ảnh xuống và phải' , image_translation )

# bây giờ, chúng ta sẽ sử dụng ma trận NumPy ở trên để dịch chuyển hình ảnh dọc theo

# hướng trục x (trái) và trục y (lên).

# Ở đây, chúng ta sẽ di chuyển hình ảnh sang bên trái 50 pixel

# và 90 pixel hướng lên trên.

dịch_mat = ví dụ. phao32 ( [ [ 1 , 0 , - năm mươi ] , [ 0 , 1 , - 90 ] ] )

image_translation = cv2. cong vênh Affine ( hình ảnh , dịch_mat ,

( hình ảnh. hình dạng [ 1 ] , hình ảnh. hình dạng [ 0 ] ) )

cv2. hiển thị ( 'Dịch hình ảnh Lên và Trái' , image_translation )

cv2. đợiKey ( 0 )

Dòng 1 đến 5: Chúng tôi đang nhập tất cả các gói cần thiết cho chương trình này, như OpenCV, argparser và NumPy. Vui lòng lưu ý rằng có một thư viện khác là imutils. Đây không phải là một gói của OpenCV. Đây chỉ là một thư viện sẽ dễ dàng hiển thị quá trình xử lý hình ảnh tương tự.



Thư viện imutils sẽ không được đưa vào tự động khi chúng ta cài đặt OpenCV. Vì vậy, để cài đặt imutils, chúng ta phải sử dụng phương pháp sau:

pip cài đặt imutils

Dòng 8 đến 15: Chúng tôi đã tạo agrparser và tải hình ảnh của mình.

Dòng 24 đến 25: Phần chương trình này là nơi dịch xảy ra. Ma trận dịch cho chúng ta biết có bao nhiêu pixel mà hình ảnh sẽ được di chuyển lên hoặc xuống hoặc sang trái hoặc phải. Bởi vì OpenCV yêu cầu giá trị ma trận nằm trong một mảng dấu phẩy động, nên ma trận dịch sẽ lấy các giá trị trong các mảng dấu phẩy động.

Hàng đầu tiên của ma trận dịch trông như thế này:

Hàng này của ma trận dành cho trục x. giá trị của t x sẽ quyết định hình ảnh sẽ được chuyển sang bên trái hay bên phải. Nếu chúng ta chuyển một giá trị âm, thì điều đó có nghĩa là hình ảnh sẽ bị dịch chuyển sang bên trái và nếu giá trị là dương, điều đó có nghĩa là hình ảnh sẽ bị dịch chuyển sang bên phải.

Bây giờ chúng ta sẽ xác định hàng thứ hai của ma trận như sau:

Hàng này của ma trận dành cho trục y. giá trị của t Y sẽ quyết định xem hình ảnh sẽ được dịch chuyển lên hay xuống. Nếu chúng ta chuyển một giá trị âm, thì điều đó có nghĩa là hình ảnh sẽ bị dịch chuyển sang phía trên và nếu giá trị dương, thì điều đó có nghĩa là hình ảnh sẽ bị dịch chuyển sang phía dưới.

Trong chương trình trước ở dòng 24, chúng ta định nghĩa t x = 30 và t Y = 70. Vì vậy, chúng tôi đang di chuyển hình ảnh 30 pixel về phía bên phải và 70 pixel xuống dưới.

Nhưng quá trình dịch ảnh chính diễn ra ở dòng 25, nơi chúng ta xác định ma trận dịch cv2.warpAffine . Trong chức năng này, chúng tôi đang truyền ba tham số: tham số đầu tiên là hình ảnh, tham số thứ hai là ma trận dịch và tham số thứ ba là kích thước hình ảnh.

Dòng 27: Dòng 27 sẽ hiển thị kết quả ở đầu ra.

Bây giờ, chúng tôi sẽ thực hiện một ma trận dịch khác cho trái và ngược. Đối với điều này, chúng ta phải xác định các giá trị âm.

Dòng 33 đến 34: Trong chương trình trước ở dòng 33, chúng ta định nghĩa t x = -50 và t Y = -90. Vì vậy, chúng tôi đang di chuyển hình ảnh 50 pixel về phía bên trái và 90 pixel lên phía trên. Nhưng quá trình dịch ảnh chính diễn ra ở dòng 34, nơi chúng ta xác định ma trận dịch cv2.warpAffine .

Dòng 36 : Dòng 36 sẽ hiển thị kết quả như ở đầu ra.

Để chạy mã trước đó, chúng ta phải cung cấp đường dẫn của hình ảnh như bên dưới.

Đầu ra: python translate.py –image con sóc.jpg

Bây giờ, chúng tôi sẽ thực hiện cùng một chương trình dịch hình ảnh bằng cách sử dụng không sử dụng được thư viện. Thư viện này rất dễ sử dụng để xử lý ảnh. Trong thư viện này, chúng ta không phải suy nghĩ về cv2.warpAffine bởi vì thư viện này sẽ lo việc này. Vì vậy, hãy triển khai chương trình dịch ảnh này bằng thư viện imutils.

Mã trăn: Chúng tôi sẽ giữ tên chương trình sau đây như translate_imutils.py .

# nhập các gói cần thiết

nhập khẩu cục mịch như ví dụ.

nhập khẩu argparse

nhập khẩu không sử dụng được

nhập khẩu cv2

# Chức năng này thực hiện dịch hình ảnh và

# trả lại hình ảnh đã dịch cho hàm gọi.

chắc chắn Phiên dịch ( hình ảnh , x , Y ) :

dịch_ma trận = ví dụ. phao32 ( [ [ 1 , 0 , x ] , [ 0 , 1 , Y ] ] )

image_translation = cv2. cong vênh Affine ( hình ảnh , dịch_ma trận ,

( hình ảnh. hình dạng [ 1 ] , hình ảnh. hình dạng [ 0 ] ) )

trở lại image_translation

# xây dựng trình phân tích cú pháp đối số và phân tích cú pháp đối số

áp dụng = argparse. Đối sốParser ( )

ap. add_argument ( '-tôi' , '--hình ảnh' , cần thiết = Thật , Cứu giúp = 'Đường dẫn đến hình ảnh' )

tranh luận = của ai ( ap. parse_args ( ) )

# tải hình ảnh và hiển thị trên màn hình

hình ảnh = cv2. imread ( tranh luận [ 'hình ảnh' ] )

cv2. hiển thị ( 'Ảnh gốc' , hình ảnh )

image_translation = imutil. Phiên dịch ( hình ảnh , 10 , 70 )

cv2. hiển thị ( 'Dịch hình ảnh sang bên phải và bên dưới' ,

image_translation )

cv2. đợiKey ( 0 )

Dòng 9 đến 13: Phần này của chương trình là nơi dịch xảy ra. Ma trận dịch thuật cho chúng ta biết bao nhiêu pixel mà hình ảnh sẽ được di chuyển lên hoặc xuống hoặc sang trái hoặc phải.

Những dòng này đã được giải thích, nhưng bây giờ chúng ta sẽ xây dựng một hàm gọi là translate() và gửi ba tham số riêng biệt vào đó. Bản thân hình ảnh đóng vai trò là tham số đầu tiên. Các giá trị x và y của ma trận dịch tương ứng với các tham số thứ hai và thứ ba.

Ghi chú : Không cần định nghĩa hàm translate này bên trong chương trình vì nó đã có sẵn trong gói thư viện imutils. Tôi đã sử dụng nó trong chương trình với mục đích giải thích đơn giản. Chúng ta có thể gọi hàm này trực tiếp bằng imutils, như trong dòng 24.

Dòng 24: Chương trình trước sẽ chỉ ra rằng ở dòng 24, chúng tôi xác định tx = 10 và ty = 70. Vì vậy, chúng tôi đang di chuyển hình ảnh 10 pixel về phía bên phải và 70 pixel xuống dưới.

Trong chương trình này, chúng tôi không quan tâm đến bất kỳ hàm cv2.warpAffine nào vì chúng đã nằm trong gói thư viện imutils.

Để chạy mã trước đó, chúng ta phải cung cấp đường dẫn của hình ảnh, như được đưa ra bên dưới:

Đầu ra:

imutils trăn py --hình ảnh con sóc. jpg

2. Xoay ảnh

Chúng ta đã xem qua cách dịch (nghĩa là dịch chuyển) một hình ảnh lên, xuống, sang trái và sang phải trong bài học trước (hoặc bất kỳ sự kết hợp nào). Tiếp theo, chúng ta sẽ thảo luận về xoay vì nó liên quan đến xử lý hình ảnh.

Một hình ảnh được xoay theo một góc, theta, trong một quá trình được gọi là xoay. Góc mà chúng ta xoay hình ảnh sẽ được biểu thị bằng theta. Ngoài ra, sau đó tôi sẽ cung cấp chức năng tiện ích xoay để giúp việc xoay hình ảnh trở nên đơn giản hơn.

Tương tự như phép tịnh tiến, và có lẽ không có gì đáng ngạc nhiên, phép quay theo một góc, theta được xác định bằng cách xây dựng một ma trận M theo định dạng sau:

Ma trận này có thể xoay một vectơ theta độ (ngược chiều kim đồng hồ) xung quanh gốc tọa độ (x, y)-mặt phẳng Descartes đã cho. Thông thường, trong trường hợp này, gốc tọa độ sẽ là tâm của bức tranh, nhưng trên thực tế, chúng ta có thể chỉ định bất kỳ điểm (x, y) ngẫu nhiên nào làm tâm xoay của mình.

Ảnh đã xoay R sau đó được tạo từ ảnh gốc I bằng cách sử dụng phép nhân ma trận đơn giản: R = IM

Mặt khác, OpenCV cung cấp thêm khả năng (1) chia tỷ lệ (nghĩa là thay đổi kích thước) một hình ảnh và (2) cung cấp một tâm xoay tùy ý để thực hiện xoay xung quanh.

Ma trận xoay M đã sửa đổi của chúng tôi được hiển thị bên dưới:

Hãy bắt đầu bằng cách mở và tạo một tệp mới có tên xoay.py :

# nhập các gói cần thiết

nhập khẩu cục mịch như ví dụ.

nhập khẩu argparse

nhập khẩu không sử dụng được

nhập khẩu cv2

# tạo đối tượng trình phân tích đối số và phân tích cú pháp đối số

apobj = argparse. Đối sốParser ( )

apobj. add_argument ( '-k' , '--hình ảnh' , cần thiết = Thật , Cứu giúp = 'đường dẫn hình ảnh' )

tranh luận = của ai ( apobj. parse_args ( ) )

hình ảnh = cv2. imread ( tranh luận [ 'hình ảnh' ] )

cv2. hiển thị ( 'Ảnh gốc' , hình ảnh )

# Tính trung tâm của hình ảnh bằng cách sử dụng kích thước của hình ảnh.

( Chiều cao , chiều rộng ) = hình ảnh. hình dạng [ : 2 ]

( trung tâmX , trung tâmY ) = ( chiều rộng / 2 , Chiều cao / 2 )

# Bây giờ, sử dụng cv2, chúng ta sẽ xoay hình ảnh 55 độ để

# xác định ma trận xoay bằng getRotationMatrix2D()

luân chuyểnma trận = cv2. getRotationMatrix2D ( ( trung tâmX , trung tâmY ) , 55 , 1.0 )

hình ảnh xoay = cv2. cong vênh Affine ( hình ảnh , luân chuyểnma trận , ( chiều rộng , Chiều cao ) )

cv2. hiển thị ( 'Xoay hình ảnh 55 độ' , hình ảnh xoay )

cv2. đợiKey ( 0 )

# Hình ảnh bây giờ sẽ được xoay -85 độ.

luân chuyểnma trận = cv2. getRotationMatrix2D ( ( trung tâmX , trung tâmY ) , - 85 , 1.0 )

hình ảnh xoay = cv2. cong vênh Affine ( hình ảnh , luân chuyểnma trận , ( chiều rộng , Chiều cao ) )

cv2. hiển thị ( 'Xoay hình ảnh theo -85 độ' , hình ảnh xoay )

cv2. đợiKey ( 0 )

Dòng 1 đến 5: Chúng tôi đang nhập tất cả các gói cần thiết cho chương trình này, như OpenCV, argparser và NumPy. Vui lòng lưu ý rằng có một thư viện khác là imutils. Đây không phải là một gói của OpenCV. Đây chỉ là một thư viện sẽ được sử dụng để hiển thị quá trình xử lý hình ảnh tương tự một cách dễ dàng.

Thư viện imutils sẽ không được đưa vào tự động khi chúng ta cài đặt OpenCV. OpenCV cài đặt imutils. Chúng ta phải sử dụng phương pháp sau:

pip cài đặt imutils

Dòng 8 đến 14: Chúng tôi đã tạo agrparser và tải hình ảnh của mình. Trong argparser này, chúng tôi chỉ sử dụng một đối số hình ảnh, đối số này sẽ cho chúng tôi biết đường dẫn của hình ảnh mà chúng tôi sẽ sử dụng trong chương trình này để minh họa phép quay.

Khi xoay một hình ảnh, chúng ta phải xác định điểm trục xoay. Hầu hết thời gian, bạn sẽ muốn xoay một hình ảnh về tâm của nó, nhưng OpenCV cho phép bạn chọn bất kỳ điểm ngẫu nhiên nào để thay thế. Hãy đơn giản là xoay hình ảnh xung quanh trung tâm của nó.

Dòng 17 đến 18 lấy chiều rộng và chiều cao của hình ảnh, tương ứng, sau đó chia mỗi chiều cho hai để thiết lập trung tâm của hình ảnh.

Chúng tôi xây dựng một ma trận để xoay một hình ảnh giống như cách chúng tôi đã xác định một ma trận để dịch một hình ảnh. Chúng tôi sẽ chỉ gọi cv2.getRotationMatrix2D chức năng trên Dòng 22 thay vì tạo ma trận theo cách thủ công bằng NumPy (có thể hơi cồng kềnh).

Các cv2.getRotationMatrix2D chức năng yêu cầu ba tham số. Đầu vào đầu tiên là góc quay mong muốn (trong trường hợp này là tâm của hình ảnh). Theta sau đó được sử dụng để chỉ định chúng ta sẽ xoay hình ảnh bao nhiêu độ (ngược chiều kim đồng hồ). Ở đây, chúng tôi sẽ xoay hình ảnh 45 độ. Tùy chọn cuối cùng liên quan đến kích thước của hình ảnh.

Bất kể thực tế là chúng ta chưa thảo luận về việc chia tỷ lệ hình ảnh, bạn có thể cung cấp số dấu phẩy động ở đây với 1.0 biểu thị rằng hình ảnh nên được sử dụng theo tỷ lệ ban đầu. Tuy nhiên, nếu bạn nhập giá trị 2.0, hình ảnh sẽ tăng gấp đôi kích thước. Một số 0,5 làm giảm kích thước của hình ảnh như thế.

Dòng 22 đến 23: Sau khi nhận được ma trận xoay M của chúng tôi từ cv2.getRotationMatrix2D chức năng, chúng tôi xoay hình ảnh của mình bằng cách sử dụng cv2.warpAffine kỹ thuật trên Dòng 23. Đầu vào đầu tiên của hàm là hình ảnh mà chúng ta muốn xoay. Chiều rộng và chiều cao của hình ảnh đầu ra của chúng tôi sau đó được xác định, cùng với ma trận xoay M của chúng tôi. Trên dòng 23, hình ảnh sau đó được xoay 55 độ.

Bạn có thể nhận thấy rằng hình ảnh của chúng tôi đã được xoay.

Dòng 28 đến 30 tạo thành vòng quay thứ hai. Các dòng 22–23 của mã giống hệt nhau, ngoại trừ lần này chúng ta đang xoay -85 độ so với 55.

Chúng tôi chỉ đơn giản là xoay một hình ảnh xung quanh tâm của nó cho đến thời điểm này. Điều gì sẽ xảy ra nếu chúng ta muốn xoay hình ảnh xung quanh một điểm ngẫu nhiên?

Hãy bắt đầu bằng cách mở và tạo một tệp mới có tên xoay.py:

# nhập các gói cần thiết

nhập khẩu cục mịch như ví dụ.

nhập khẩu argparse

nhập khẩu không sử dụng được

nhập khẩu cv2

# tạo đối tượng trình phân tích đối số và phân tích cú pháp đối số

ap_obj = argparse. Đối sốParser ( )

ap_obj. add_argument ( '-k' , '--hình ảnh' , cần thiết = Thật , Cứu giúp = 'đường dẫn hình ảnh' )

tranh luận = của ai ( ap_obj. parse_args ( ) )

# tải hình ảnh và hiển thị trên màn hình

hình ảnh = cv2. imread ( tranh luận [ 'hình ảnh' ] )

cv2. hiển thị ( 'Ảnh gốc' , hình ảnh )

# Tính trung tâm của hình ảnh bằng cách sử dụng kích thước của hình ảnh.

( Chiều cao , chiều rộng ) = hình ảnh. hình dạng [ : 2 ]

( trung tâmX , trung tâmY ) = ( chiều rộng / 2 , Chiều cao / 2 )

# Bây giờ, sử dụng cv2, chúng ta sẽ xoay hình ảnh 55 độ để

# xác định ma trận xoay bằng getRotationMatrix2D()

luân chuyểnma trận = cv2. getRotationMatrix2D ( ( trung tâmX , trung tâmY ) , 55 , 1.0 )

hình ảnh xoay = cv2. cong vênh Affine ( hình ảnh , luân chuyểnma trận , ( chiều rộng , Chiều cao ) )

cv2. hiển thị ( 'Xoay hình ảnh 55 độ' , hình ảnh xoay )

cv2. đợiKey ( 0 )

# Hình ảnh bây giờ sẽ được xoay -85 độ.

luân chuyểnma trận = cv2. getRotationMatrix2D ( ( trung tâmX , trung tâmY ) , - 85 , 1.0 )

hình ảnh xoay = cv2. cong vênh Affine ( hình ảnh , luân chuyểnma trận , ( chiều rộng , Chiều cao ) )

cv2. hiển thị ( 'Xoay hình ảnh theo -85 độ' , hình ảnh xoay )

cv2. đợiKey ( 0 )

# xoay hình ảnh từ một số điểm tùy ý, không phải từ trung tâm

luân chuyểnma trận = cv2. getRotationMatrix2D ( ( trung tâmX - 40 , tâmY - 40 ) , 55 , 1.0 )

hình ảnh xoay = cv2. cong vênh Affine ( hình ảnh , luân chuyểnma trận , ( chiều rộng , Chiều cao ) )

cv2. hiển thị ( 'Xoay ảnh từ các điểm tùy ý' , hình ảnh xoay )

cv2. đợiKey ( 0 )

Dòng 34 đến 35: Bây giờ, mã này có vẻ khá phổ biến để xoay một đối tượng. Để xoay hình ảnh xung quanh một điểm 40 pixel về bên trái và 40 pixel phía trên tâm của nó, chúng tôi hướng dẫn cv2.getRotationMatrix2D chức năng chú ý đến tham số đầu tiên của nó.

Hình ảnh được tạo ra khi chúng ta áp dụng phép xoay này được hiển thị bên dưới:

Chúng ta có thể thấy rõ ràng tâm của vòng xoay giờ là tọa độ (x, y), nằm 40 pixel ở bên trái và 40 pixel ở trên trung tâm được tính toán của ảnh.

3. Số học hình ảnh

Trên thực tế, số học hình ảnh chỉ là phép cộng ma trận với một số hạn chế bổ sung đối với các loại dữ liệu mà chúng tôi sẽ đề cập sau.

Hãy dành một chút thời gian để xem qua một số nguyên tắc khá cơ bản của đại số tuyến tính.

Xem xét kết hợp hai ma trận tiếp theo:

Phép cộng ma trận sẽ tạo ra kết quả gì? Câu trả lời đơn giản là tổng của các mục ma trận, từng phần tử:

Đủ đơn giản, phải không?

Tất cả chúng ta đều hiểu các phép toán cơ bản của phép cộng và phép trừ vào thời điểm này. Tuy nhiên, chúng ta phải lưu ý đến những hạn chế do không gian màu và kiểu dữ liệu áp đặt khi làm việc với hình ảnh.

Ví dụ, các điểm ảnh trong hình ảnh RGB nằm trong khoảng [0, 255]. Điều gì xảy ra nếu chúng ta cố gắng thêm 10 vào một pixel có cường độ 250 khi nhìn vào nó?

Chúng tôi sẽ đạt được giá trị 260 nếu chúng tôi áp dụng các nguyên tắc số học tiêu chuẩn. 260 không phải là giá trị hợp lệ vì hình ảnh RGB được biểu thị dưới dạng số nguyên không dấu 8 bit.

Vì vậy, những gì nên xảy ra? Chúng ta có nên chạy kiểm tra để đảm bảo không có pixel nào nằm ngoài phạm vi [0, 255], cắt từng pixel để có giá trị trong khoảng từ 0 đến 255 không?

Hay chúng ta “quấn xung quanh” và thực hiện một phép toán mô đun? Theo các quy tắc mô đun, việc thêm 10 vào 255 sẽ chỉ dẫn đến giá trị là 9.

Các phép cộng và phép trừ đối với hình ảnh nằm ngoài phạm vi [0, 255] nên được xử lý như thế nào?

Sự thật là không có kỹ thuật đúng hay sai; tất cả phụ thuộc vào cách bạn đang làm việc với pixel của mình và những gì bạn hy vọng đạt được.

Nhưng hãy nhớ rằng có sự khác biệt giữa phần bổ sung trong OpenCV và phần bổ sung trong NumPy. Số học mô-đun và 'quấn xung quanh' sẽ được thực hiện bởi NumPy. Ngược lại, OpenCV sẽ thực hiện cắt xén và đảm bảo rằng các giá trị pixel không bao giờ rời khỏi phạm vi [0, 255].

Hãy bắt đầu bằng cách tạo một tệp mới có tên số học.py và mở nó:

# python arithmetic.py --image con sóc.jpg

# nhập các gói cần thiết

nhập khẩu cục mịch như ví dụ.

nhập khẩu argparse

nhập khẩu không sử dụng được

nhập khẩu cv2

# tạo đối tượng trình phân tích đối số và phân tích cú pháp đối số

apObj = argparse. Đối sốParser ( )

apObj. add_argument ( '-k' , '--hình ảnh' , cần thiết = Thật , Cứu giúp = 'đường dẫn hình ảnh' )

tranh luận = của ai ( apObj. parse_args ( ) )

hình ảnh = cv2. imread ( tranh luận [ 'hình ảnh' ] )

cv2. hiển thị ( 'Ảnh gốc' , hình ảnh )

'''

Các giá trị của pixel của chúng tôi sẽ nằm trong phạm vi [0, 255]

vì hình ảnh là mảng NumPy, được lưu trữ dưới dạng số nguyên 8 bit không dấu.

Khi sử dụng các hàm như cv2.add và cv2.subtract, các giá trị sẽ bị cắt bớt

vào phạm vi này ngay cả khi chúng được thêm vào hoặc bớt đi từ bên ngoài phạm vi

[0, 255] phạm vi. Đây là một minh họa:

'''


in ( 'tối đa 255: {}' . định dạng ( str ( cv2. cộng ( ví dụ. uint8 ( [ 201 ] ) ,

ví dụ. uint8 ( [ 100 ] ) ) ) ) )

in ( 'tối thiểu 0: {}' . định dạng ( str ( cv2. trừ đi ( ví dụ. uint8 ( [ 60 ] ) ,

ví dụ. uint8 ( [ 100 ] ) ) ) ) )

'''

Khi thực hiện các phép toán số học với các mảng này bằng NumPy,

giá trị sẽ bao quanh thay vì được cắt bớt vào

[0, 255]phạm vi. Khi sử dụng hình ảnh, điều cần thiết là phải giữ

trong tâm trí.

'''


in ( 'quấn quanh: {}' . định dạng ( str ( ví dụ. uint8 ( [ 201 ] ) + v.d. uint8 ( [ 100 ] ) ) ) )

in ( 'quấn quanh: {}' . định dạng ( str ( ví dụ. uint8 ( [ 60 ] ) - ví dụ. uint8 ( [ 100 ] ) ) ) )

'''

Hãy nhân độ sáng của mỗi pixel trong hình ảnh của chúng ta với 101.

Để làm điều này, chúng tôi tạo một mảng NumPy có cùng kích thước với ma trận của chúng tôi,

được lấp đầy bằng những cái và nhân nó với 101 để tạo ra một mảng được lấp đầy

với 101s. Cuối cùng, chúng tôi hợp nhất hai hình ảnh.

Bạn sẽ lưu ý rằng hình ảnh bây giờ 'sáng hơn'.

'''


ma trận = ví dụ. những cái ( hình ảnh. hình dạng , = 'uint8' ) * 101

image_add = cv2. cộng ( hình ảnh , ma trận )

cv2. hiển thị ( 'Đã thêm kết quả hình ảnh' , image_add )

# Theo cách tương tự, chúng tôi có thể làm cho hình ảnh của mình tối hơn bằng cách chụp

# 60 cách xa tất cả các pixel.

ma trận = ví dụ. những cái ( hình ảnh. hình dạng , = 'uint8' ) * 60

image_subtracted = cv2. trừ đi ( hình ảnh , ma trận )

cv2. hiển thị ( 'Kết quả hình ảnh bị trừ' , image_subtracted )

cv2. đợiKey ( 0 )

Dòng 1 đến 16 sẽ được sử dụng để thực hiện quy trình thông thường của chúng tôi, bao gồm nhập các gói của chúng tôi, định cấu hình trình phân tích cú pháp đối số và tải hình ảnh của chúng tôi.

Nhớ lại cách tôi đã thảo luận trước đây về sự khác biệt giữa OpenCV và bổ sung NumPy? Bây giờ chúng tôi đã đề cập kỹ lưỡng về nó, hãy xem xét một trường hợp cụ thể để đảm bảo chúng tôi nắm bắt được nó.

Hai mảng NumPy số nguyên không dấu 8 bit được xác định trên dòng 26 . Giá trị 201 là phần tử duy nhất trong mảng đầu tiên. Mặc dù chỉ có một thành viên trong mảng thứ hai, nhưng nó có giá trị là 100. Sau đó, các giá trị này được thêm vào bằng cách sử dụng hàm cv2.add của OpenCV.

Bạn dự đoán kết quả là gì?

Theo các nguyên tắc số học thông thường, câu trả lời phải là 301. Nhưng hãy nhớ rằng chúng ta đang xử lý các số nguyên không dấu 8 bit, chỉ có thể nằm trong phạm vi [0, 255]. Bởi vì chúng ta đang sử dụng phương thức cv2.add, OpenCV xử lý việc cắt xén và đảm bảo rằng phép cộng chỉ trả về kết quả tối đa là 255.

Dòng đầu tiên của danh sách dưới đây cho thấy kết quả của việc chạy mã này:

Môn số học. py

tối đa của 255 : [ [ 255 ] ]

Tổng thực sự đã tạo ra một số 255.

Theo đó, dòng 26 sử dụng cv2.subtract để thực hiện phép trừ. Một lần nữa, chúng tôi xác định hai mảng NumPy số nguyên không dấu 8 bit với một phần tử duy nhất trong mỗi mảng. Giá trị của mảng đầu tiên là 60, trong khi giá trị của mảng thứ hai là 100.

Số học của chúng tôi chỉ ra rằng phép trừ sẽ dẫn đến giá trị -40, nhưng OpenCV xử lý việc cắt bớt cho chúng tôi một lần nữa. Chúng tôi phát hiện ra rằng giá trị đã được cắt thành 0. Kết quả của chúng tôi dưới đây chứng minh điều này:

Môn số học. py

tối thiểu của 0 : [ [ 0 ] ]

Sử dụng cv2, trừ 100 từ 60 trừ, tạo ra giá trị 0.

Nhưng điều gì sẽ xảy ra nếu chúng ta sử dụng NumPy thay cho OpenCV để thực hiện các tính toán?

Dòng 38 và 39 giải quyết vấn đề này.

Đầu tiên, hai mảng NumPy số nguyên không dấu 8 bit với một phần tử duy nhất được xác định. Giá trị của mảng đầu tiên là 201, trong khi giá trị của mảng thứ hai là 100. Phần bổ sung của chúng ta sẽ bị cắt bớt và giá trị 255 sẽ được trả về nếu chúng ta sử dụng hàm cv2.add.

Mặt khác, NumPy “bao quanh” và thực hiện phép tính số học modulo thay vì cắt bớt. NumPy kết thúc bằng 0 sau khi đạt đến giá trị 255 và sau đó tiếp tục đếm cho đến khi đạt được 100 bước. Điều này được xác nhận bởi dòng đầu ra đầu tiên, được hiển thị bên dưới:

Môn số học. py
quấn quanh: [ Bốn năm ]

Sau đó, hai mảng NumPy nữa được xác định, một mảng có giá trị 50 và mảng kia có giá trị 100. Phép trừ này sẽ được cắt bớt bởi phương thức cv2.subtract để trả về kết quả là 0. Nhưng chúng tôi biết rằng thay vì cắt bớt, NumPy thực thi số học modulo. Thay vào đó, các thủ tục modulo bao quanh và bắt đầu đếm ngược từ 255 sau khi đạt đến 0 trong phép trừ. Chúng ta có thể thấy điều này từ đầu ra sau:

Môn số học. py

quấn quanh: [ 207 ]

Một lần nữa, đầu ra thiết bị đầu cuối của chúng tôi cho thấy sự khác biệt giữa cắt và quấn xung quanh:

Điều quan trọng là phải ghi nhớ kết quả mong muốn của bạn khi thực hiện phép tính số nguyên. Bạn có muốn cắt bất kỳ giá trị nào nằm ngoài phạm vi [0, 255] không? Sau đó, hãy sử dụng các kỹ thuật số học hình ảnh tích hợp sẵn của OpenCV.

Bạn có muốn các giá trị bao quanh nếu chúng nằm ngoài phạm vi [0, 255] và các phép toán số học mô đun không? Các mảng NumPy sau đó được cộng và trừ đơn giản như bình thường.

dòng 48 xác định mảng NumPy một chiều có cùng kích thước với hình ảnh của chúng tôi. Một lần nữa, chúng tôi đảm bảo rằng kiểu dữ liệu của chúng tôi là số nguyên không dấu 8 bit. Chúng tôi chỉ nhân ma trận các giá trị một chữ số với 101 để điền vào đó các giá trị 101 thay vì 1. Cuối cùng, chúng tôi sử dụng hàm cv2.add để thêm ma trận 100 vào hình ảnh gốc. Điều này làm tăng cường độ của mỗi pixel lên 101 đồng thời đảm bảo rằng mọi giá trị cố gắng vượt quá 255 đều được cắt bớt trong phạm vi [0, 255].

Hãy quan sát xem hình ảnh sáng hơn rõ rệt như thế nào và có vẻ 'mờ' hơn so với ban đầu. Điều này là do chúng tôi đang hướng các pixel về phía màu sáng hơn bằng cách tăng cường độ pixel của chúng lên 101.

Để trừ 60 từ mỗi cường độ pixel của hình ảnh, trước tiên chúng tôi thiết lập một mảng NumPy thứ hai trên Dòng 54 được lấp đầy bằng 60 giây.

Kết quả của phép trừ này được mô tả trong hình ảnh sau:

Các vật phẩm xung quanh chúng ta có vẻ tối hơn đáng kể so với trước đây. Điều này là do bằng cách trừ đi 60 cho mỗi pixel, chúng tôi sẽ di chuyển các pixel trong không gian màu RGB sang các vùng tối hơn.

4. Lật ảnh

Tương tự như xoay, lật hình ảnh qua trục x hoặc y của nó là một tùy chọn khác do OpenCV cung cấp. Ngay cả khi các thao tác lật không được sử dụng thường xuyên, thì việc biết chúng cũng vô cùng hữu ích vì nhiều lý do mà bạn có thể không thấy ngay.

Chúng tôi đang phát triển một bộ phân loại máy học cho một công ty nhỏ mới thành lập đang tìm cách nhận dạng khuôn mặt trong hình ảnh. Để hệ thống của chúng tôi “tìm hiểu” khuôn mặt là gì, chúng tôi sẽ cần một số loại tập dữ liệu có khuôn mặt mẫu. Thật không may, công ty chỉ cung cấp cho chúng tôi một tập dữ liệu nhỏ gồm 40 khuôn mặt và chúng tôi không thể thu thập thêm thông tin.

Vậy chúng ta làm gì?

Vì một khuôn mặt vẫn là một khuôn mặt cho dù nó có được nhân đôi hay không, nên chúng tôi có thể lật từng hình ảnh của khuôn mặt theo chiều ngang và sử dụng các phiên bản được nhân đôi làm dữ liệu huấn luyện bổ sung.

Ví dụ này có vẻ ngu ngốc và giả tạo, nhưng không phải vậy. Lật là một chiến lược có chủ ý được sử dụng bởi các thuật toán học sâu mạnh mẽ để tạo ra nhiều dữ liệu hơn trong giai đoạn đào tạo.

Rõ ràng từ phần trước rằng các phương pháp xử lý hình ảnh mà bạn học trong mô-đun này đóng vai trò là nền tảng cho các hệ thống thị giác máy tính lớn hơn.

Mục tiêu:

Sử dụng cv2.flip chức năng, bạn sẽ học cách lật hình ảnh theo cả chiều ngang và chiều dọc trong phần này.

Lật là thao tác hình ảnh tiếp theo mà chúng ta sẽ nghiên cứu. Có thể lật trục x và trục y của hình ảnh hoặc thậm chí cả hai. Trước khi chúng ta đi sâu vào mã hóa, tốt nhất là trước tiên hãy xem kết quả của một lần lật hình ảnh. Xem một hình ảnh đã được lật theo chiều ngang trong hình ảnh sau đây:


Lưu ý cách hình ảnh gốc của chúng ta ở bên trái và cách hình ảnh được phản chiếu theo chiều ngang ở bên phải.

Hãy bắt đầu bằng cách tạo một tệp mới có tên flipping.py .

Bạn đã thấy một ví dụ về lật hình ảnh, vì vậy hãy kiểm tra mã:

# python flipping.py --image quirrel.jpg

# nhập các gói cần thiết

nhập khẩu argparse

nhập khẩu cv2

# tạo đối tượng của trình phân tích cú pháp đối số và phân tích cú pháp đối số

apObj = argparse. Đối sốParser ( )

apObj. add_argument ( '-tôi' , '--hình ảnh' , cần thiết = Thật , Cứu giúp = 'đường dẫn hình ảnh' )

tranh luận = của ai ( apObj. parse_args ( ) )

hình ảnh = cv2. imread ( tranh luận [ 'hình ảnh' ] )

cv2. hiển thị ( 'Nguyên' , hình ảnh )

# lật ảnh theo chiều ngang

lật ngược hình ảnh = cv2. lật ( hình ảnh , 1 )

cv2. hiển thị ( 'Lật ảnh theo chiều ngang' , lật ngược hình ảnh )

# lật ảnh theo chiều dọc

lật ngược hình ảnh = cv2. lật ( hình ảnh , 0 )

cv2. hiển thị ( 'Hình ảnh lật theo chiều dọc' , lật ngược hình ảnh )

# hình ảnh lật dọc theo cả hai trục

lật ngược hình ảnh = cv2. lật ( hình ảnh , - 1 )

cv2. hiển thị ( 'Lật ngang & dọc' , lật ngược hình ảnh )

cv2. đợiKey ( 0 )

Các bước chúng tôi thực hiện để nhập gói, phân tích cú pháp đầu vào và tải hình ảnh từ đĩa được xử lý trong l từ 1 đến 12 .

Bằng cách gọi hàm cv2.flip trên dòng 15 , thật đơn giản để lật một hình ảnh theo chiều ngang. Hình ảnh mà chúng tôi muốn lật và một mã hoặc cờ cụ thể chỉ định cách lật hình ảnh là hai đối số cần thiết cho phương thức cv2.flip.

Giá trị mã lật là 1 có nghĩa là chúng ta sẽ xoay ảnh quanh trục y để lật ảnh theo chiều ngang ( dòng 15 ). Nếu chúng tôi chỉ định mã lật là 0, chúng tôi muốn xoay hình ảnh về trục x ( Dòng 19 ). Mã lật ngược âm ( Dòng 23 ) xoay hình ảnh trên cả hai trục.

Một trong những ví dụ đơn giản nhất trong chủ đề này là lật một hình ảnh, đây là thao tác cơ bản.

Tiếp theo, chúng ta sẽ thảo luận về việc cắt xén hình ảnh và sử dụng các lát mảng NumPy để trích xuất các phần hình ảnh cụ thể.

5. Cắt ảnh

Cắt xén, như tên của nó, là quá trình chọn và xóa Vùng quan tâm (hoặc đơn giản là ROI), là vùng hình ảnh mà chúng ta quan tâm.

Khuôn mặt sẽ phải được cắt từ một hình ảnh cho ứng dụng nhận diện khuôn mặt. Ngoài ra, nếu chúng tôi đang tạo tập lệnh Python để tìm chó trong hình ảnh, chúng tôi có thể muốn cắt con chó ra khỏi hình ảnh khi chúng tôi xác định vị trí của nó.

Bàn thắng: Mục tiêu chính của chúng tôi là trở nên quen thuộc và dễ dàng sử dụng kỹ thuật cắt mảng NumPy để cắt các vùng từ một hình ảnh.

cắt xén : Khi chúng tôi cắt ảnh, mục tiêu của chúng tôi là loại bỏ các yếu tố bên ngoài mà chúng tôi không quan tâm. Quá trình chọn ROI của chúng tôi thường được gọi là chọn khu vực chúng tôi quan tâm.

Tạo một tệp mới có tên crop.py , mở nó và thêm đoạn mã sau:

# trăn crop.py

# nhập các gói cần thiết

nhập khẩu cv2

# tải hình ảnh và hiển thị trên màn hình

hình ảnh = cv2. imread ( 'con sóc.jpg' )

in ( hình ảnh. hình dạng )

cv2. hiển thị ( 'Nguyên' , hình ảnh )

# Các lát mảng NumPy được sử dụng để cắt nhanh một hình ảnh

# chúng ta sẽ cắt khuôn mặt con sóc khỏi hình ảnh

mặt sóc = hình ảnh [ 35 : 90 , 35 : 100 ]

cv2. hiển thị ( 'mặt sóc' , mặt sóc )

cv2. đợiKey ( 0 )

# Và bây giờ, ở đây chúng ta sẽ cắt toàn bộ cơ thể

# con sóc

thân sóc = hình ảnh [ 35 : 148 , 23 : 143 ]

cv2. hiển thị ( 'Thân sóc' , thân sóc )

cv2. đợiKey ( 0 )

Chúng tôi sẽ hiển thị cắt xén trong Python và OpenCV bằng hình ảnh mà chúng tôi tải từ đĩa trên Dòng 5 và 6 .

Hình ảnh gốc mà chúng ta sẽ cắt

Chỉ sử dụng các kỹ thuật cắt xén cơ bản, chúng tôi muốn tách mặt sóc và thân sóc ra khỏi khu vực xung quanh.

Chúng tôi sẽ sử dụng kiến ​​thức trước đây của mình về hình ảnh và cung cấp thủ công các lát mảng NumPy về vị trí tồn tại của cơ thể và khuôn mặt. Trong điều kiện bình thường, chúng tôi thường sử dụng thuật toán máy học và thị giác máy tính để nhận dạng khuôn mặt và cơ thể trong ảnh. Nhưng hãy giữ mọi thứ đơn giản trong thời điểm hiện tại và tránh sử dụng bất kỳ mô hình phát hiện nào.

Chúng ta có thể nhận dạng khuôn mặt trong ảnh chỉ bằng một dòng mã. Dòng 13 , Để trích xuất một phần hình chữ nhật của hình ảnh, bắt đầu từ (35, 35), chúng tôi cung cấp các lát mảng NumPy (90, 100). Có vẻ khó hiểu khi chúng tôi cung cấp cho cây trồng các chỉ mục theo thứ tự chiều cao thứ nhất và chiều rộng thứ hai mà chúng tôi thực hiện, nhưng hãy nhớ rằng OpenCV lưu trữ hình ảnh dưới dạng mảng NumPy. Do đó, chúng tôi phải cung cấp các giá trị cho trục y trước trục x.

NumPy yêu cầu bốn chỉ mục sau để thực hiện việc cắt xén của chúng tôi:

Bắt đầu y: Tọa độ y lúc đầu. Đối với trường hợp này, chúng tôi bắt đầu tại y=35.

Kết thúc: Tọa độ y ở cuối. Cây trồng của chúng tôi sẽ dừng lại khi y = 90.

Bắt đầu x: Tọa độ x bắt đầu của lát cắt. Cây trồng được bắt đầu tại x=35.

Kết thúc x: Tọa độ trục x cuối của lát cắt. Tại x=100, lát cắt của chúng ta đã hoàn thành.

Tương tự, chúng ta cắt các vùng (23, 35) và (143, 148) từ ảnh gốc để trích xuất toàn bộ cơ thể từ ảnh trên Dòng 19 .

Bạn có thể nhận thấy rằng hình ảnh đã được cắt để chỉ hiển thị cơ thể và khuôn mặt.

6. Thay đổi kích thước hình ảnh

Quá trình tăng hoặc giảm chiều rộng và chiều cao của hình ảnh được gọi là chia tỷ lệ hoặc đơn giản là thay đổi kích thước. Tỷ lệ khung hình, là tỷ lệ giữa chiều rộng và chiều cao của hình ảnh, nên được xem xét khi thay đổi kích thước hình ảnh. Việc bỏ qua tỷ lệ khung hình có thể dẫn đến hình ảnh đã được thu nhỏ có vẻ như bị nén và biến dạng:

Hình ảnh ban đầu của chúng tôi ở bên trái. Ở bên phải, bạn sẽ thấy hai hình ảnh đã được thu nhỏ mà không duy trì tỷ lệ khung hình, làm biến dạng tỷ lệ chiều rộng của hình ảnh so với chiều cao của hình ảnh. Khi thay đổi kích thước hình ảnh của bạn, bạn thường nên xem xét tỷ lệ khung hình.

Kỹ thuật nội suy được sử dụng bởi thuật toán thay đổi kích thước của chúng tôi cũng phải xem xét mục tiêu của hàm nội suy để sử dụng các vùng lân cận pixel này để tăng hoặc giảm kích thước của hình ảnh.

Nói chung, thu nhỏ kích thước của hình ảnh hiệu quả hơn nhiều. Điều này là do việc xóa pixel khỏi hình ảnh là tất cả chức năng nội suy cần thực hiện. Mặt khác, phương pháp nội suy sẽ cần phải “điền vào các khoảng trống” giữa các pixel không tồn tại trước đây nếu kích thước hình ảnh được tăng lên.

Chúng tôi có hình ảnh ban đầu của chúng tôi ở bên trái. Hình ảnh đã được giảm xuống một nửa kích thước ban đầu của nó ở trung tâm, nhưng ngoài điều đó ra, “chất lượng” của hình ảnh không bị giảm đi. Tuy nhiên, kích thước của hình ảnh đã được tăng cường đáng kể ở bên phải. Bây giờ nó xuất hiện 'bị nổ tung' và 'có điểm ảnh'.

Như tôi đã nói trước đây, thông thường bạn sẽ muốn giảm kích thước của hình ảnh hơn là tăng kích thước của nó. Bằng cách giảm kích thước hình ảnh, chúng tôi phân tích ít pixel hơn và phải xử lý ít “nhiễu” hơn, giúp các thuật toán xử lý hình ảnh nhanh hơn và chính xác hơn.

Dịch và xoay là hai phép biến đổi hình ảnh được đề cập cho đến nay. Bây giờ chúng ta sẽ xem xét cách thay đổi kích thước hình ảnh.

Không có gì đáng ngạc nhiên, chúng tôi sẽ thay đổi kích thước hình ảnh của mình bằng phương pháp cv2.resize. Như tôi đã chỉ ra trước đó, chúng ta phải xem xét tỷ lệ khung hình của hình ảnh khi sử dụng phương pháp này. Nhưng trước khi chúng ta đi quá sâu vào các chi tiết cụ thể, hãy cho phép tôi đưa ra một minh họa:

# python resize.py --image con sóc.jpg

# nhập các gói cần thiết

nhập khẩu argparse

nhập khẩu cv2

# tạo đối tượng của trình phân tích cú pháp đối số và phân tích cú pháp đối số

apObj = argparse. Đối sốParser ( )

apObj. add_argument ( '-k' , '--hình ảnh' , cần thiết = Thật , Cứu giúp = 'đường dẫn hình ảnh' )

tranh luận = của ai ( apObj. parse_args ( ) )

# tải hình ảnh và hiển thị trên màn hình

hình ảnh = cv2. imread ( tranh luận [ 'hình ảnh' ] )

cv2. hiển thị ( 'Nguyên' , hình ảnh )

# Để hình ảnh không bị lệch, tỷ lệ khung hình

# phải được xem xét hoặc biến dạng; do đó, chúng tôi tìm ra những gì

# tỷ lệ của hình ảnh mới so với hình ảnh hiện tại.

# Hãy tạo chiều rộng của hình ảnh mới của chúng ta là 160 pixel.

diện mạo = 160.0 / hình ảnh. hình dạng [ 1 ]

kích thước = ( 160 , int ( hình ảnh. hình dạng [ 0 ] * diện mạo ) )

# dòng này sẽ hiển thị các hoạt động thay đổi kích thước thực tế

thay đổi kích thước hình ảnh = cv2. thay đổi kích thước ( hình ảnh , kích thước , nội suy = cv2. INTER_AREA )

cv2. hiển thị ( 'Đã thay đổi kích thước chiều rộng hình ảnh' , thay đổi kích thước hình ảnh )

# Nếu chúng ta muốn thay đổi chiều cao của hình ảnh thì sao? - sử dụng

# nguyên tắc tương tự, chúng ta có thể tính tỷ lệ khung hình dựa trên

# trên chiều cao thay vì chiều rộng. Hãy làm cho quy mô

# chiều cao của hình ảnh là 70 pixel.

diện mạo = 70,0 / hình ảnh. hình dạng [ 0 ]

kích thước = ( int ( hình ảnh. hình dạng [ 1 ] * diện mạo ) , 70 )

# thực hiện thay đổi kích thước

thay đổi kích thước hình ảnh = cv2. thay đổi kích thước ( hình ảnh , kích thước , nội suy = cv2. INTER_AREA )

cv2. hiển thị ( 'Đã thay đổi kích thước chiều cao hình ảnh' , thay đổi kích thước hình ảnh )

cv2. đợiKey ( 0 )

Dòng 1-14 , Sau khi nhập các gói của chúng tôi và định cấu hình trình phân tích cú pháp đối số của chúng tôi, chúng tôi sẽ tải và hiển thị hình ảnh của chúng tôi.

Dòng 20 và 21: Mã liên quan bắt đầu trong những dòng này . Tỷ lệ khung hình của hình ảnh phải được xem xét trong khi thay đổi kích thước hình ảnh. Tỷ lệ giữa chiều rộng và chiều cao của hình ảnh được gọi là tỷ lệ khung hình.

Chiều cao chiều rộng là tỷ lệ khung hình.

Nếu chúng tôi không xem xét tỷ lệ khung hình, kết quả thay đổi kích thước của chúng tôi sẽ bị sai lệch.

Trên Dòng 20 , phép tính tỷ lệ đã thay đổi kích thước được thực hiện. Chúng tôi cung cấp chiều rộng của hình ảnh mới là 160 pixel trong dòng mã này. Chúng tôi chỉ cần xác định tỷ lệ (aspectratio) của mình là chiều rộng mới (160 pixel) chia cho chiều rộng cũ mà chúng tôi truy cập bằng hình ảnh để tính tỷ lệ giữa chiều cao mới với chiều cao cũ. hình dạng [1].

Các kích thước mới của hình ảnh trên Dòng 21 có thể được tính toán ngay bây giờ khi chúng ta biết tỷ lệ của mình. Một lần nữa, hình ảnh mới sẽ có chiều rộng 160 pixel. Sau khi nhân chiều cao cũ với tỷ lệ của chúng tôi và chuyển đổi kết quả thành một số nguyên, chiều cao được tính toán. Chúng tôi có thể duy trì tỷ lệ khung hình gốc của hình ảnh bằng cách thực hiện thao tác này.

Dòng 24 là nơi hình ảnh thực sự được thay đổi kích thước. Hình ảnh chúng tôi muốn thay đổi kích thước là đối số đầu tiên và đối số thứ hai là kích thước chúng tôi đã tính cho hình ảnh mới. Phương pháp nội suy của chúng tôi, là thuật toán thay đổi kích thước hình ảnh thực tế, là tham số cuối cùng.

Cuối cùng, trên Dòng 25 , chúng tôi hiển thị hình ảnh được chia tỷ lệ của mình.

Chúng tôi xác định lại tỷ lệ của chúng tôi (aspectratio) trên Dòng 31 . Chiều cao của hình ảnh mới của chúng tôi sẽ là 70 pixel. Chúng tôi chia 70 cho chiều cao ban đầu để có tỷ lệ chiều cao mới so với chiều cao ban đầu.

Tiếp theo, chúng tôi thiết lập kích thước của hình ảnh mới. Hình ảnh mới sẽ có chiều cao 70 pixel, đã được biết trước. Một lần nữa, chúng ta có thể giữ nguyên tỷ lệ khung hình ban đầu của hình ảnh bằng cách nhân chiều rộng cũ với tỷ lệ để tạo ra chiều rộng mới.

Hình ảnh sau đó thực sự được thay đổi kích thước trên Dòng 35 , và nó được hiển thị trên Dòng 36.

Ở đây, chúng ta có thể thấy rằng chúng ta đã giảm chiều rộng và chiều cao của hình ảnh ban đầu trong khi vẫn giữ nguyên tỷ lệ khung hình. Hình ảnh của chúng tôi sẽ bị biến dạng nếu tỷ lệ khung hình không được duy trì.

Phần kết luận

Trong blog này, chúng tôi đã nghiên cứu các khái niệm xử lý hình ảnh cơ bản khác nhau. Chúng tôi đã thấy bản dịch hình ảnh với sự trợ giúp của gói OpenCV. Chúng ta đã thấy các phương pháp để di chuyển hình ảnh lên, xuống, phải và trái. Các phương pháp này rất hữu ích khi chúng ta tạo một tập dữ liệu gồm các hình ảnh tương tự để làm tập dữ liệu huấn luyện, vì vậy máy sẽ thấy các hình ảnh khác nhau ngay cả khi chúng giống nhau. Bài viết này cũng hướng dẫn bạn cách xoay một hình ảnh quanh bất kỳ điểm nào trong không gian Descartes bằng cách sử dụng ma trận xoay. Sau đó, bạn đã khám phá ra cách OpenCV xoay hình ảnh bằng cách sử dụng ma trận này và xem một vài minh họa về hình ảnh xoay.

Hai phép toán số học hình ảnh cơ bản (nhưng quan trọng) là phép cộng và phép trừ đã được xem xét trong phần này. Như bạn có thể thấy, cộng và trừ các ma trận cơ bản là tất cả các phép toán số học hình ảnh đòi hỏi.

Ngoài ra, chúng tôi đã sử dụng OpenCV và NumPy để điều tra các đặc thù của số học hình ảnh. Những hạn chế này phải được ghi nhớ, nếu không bạn có nguy cơ nhận được kết quả không mong muốn khi thực hiện các phép toán số học trên hình ảnh của mình.

Điều quan trọng cần nhớ là mặc dù NumPy thực hiện thao tác mô đun và 'bao quanh', phép cộng và phép trừ của OpenCV cắt các giá trị vượt ra ngoài phạm vi [0, 255] để vừa với phạm vi. Khi phát triển các ứng dụng thị giác máy tính của riêng bạn, ghi nhớ điều này sẽ giúp bạn tránh phải săn lùng các lỗi phức tạp.

Lật ảnh chắc chắn là một trong những ý tưởng đơn giản hơn mà chúng ta sẽ khám phá trong khóa học này. Lật thường được sử dụng trong học máy để tạo ra nhiều mẫu dữ liệu đào tạo hơn, dẫn đến các bộ phân loại hình ảnh mạnh mẽ và đáng tin cậy hơn.

Chúng tôi cũng đã học cách sử dụng OpenCV để thay đổi kích thước hình ảnh. Điều quan trọng là phải xem xét cả phương pháp nội suy mà bạn đang sử dụng và tỷ lệ khung hình của hình ảnh gốc khi thay đổi kích thước hình ảnh để kết quả không bị biến dạng.

Cuối cùng, điều quan trọng cần nhớ là nếu chất lượng hình ảnh là một vấn đề, tốt nhất bạn nên chuyển từ hình ảnh lớn hơn sang hình ảnh nhỏ hơn. Trong hầu hết các trường hợp, việc phóng to hình ảnh sẽ tạo ra hiện vật giả và làm giảm chất lượng của nó.