Cách tạo tệp jpg trong Python

Tham số đầu tiên là đường dẫn chứa hình ảnh. Tham số thứ hai là cờ cho chúng ta biết hình ảnh nên được đọc như thế nào. Các tùy chọn cho tham số cờ là

  • cv2. IMREAD_COLOR hoặc 1. Đây là giá trị mặc định và sẽ tải hình ảnh màu
  • cv2. IMREAD_GRAYSCALE hoặc 0. sẽ tải hình ảnh theo thang độ xám
  • cv2. IMREAD_UNCHANGED hoặc -1. Tải hình ảnh như vậy, bao gồm cả kênh alpha

imshow[] hiển thị hình ảnh trong cửa sổ

Tham số đầu tiên là tên cửa sổ và tham số thứ hai là hình ảnh

waitKey[] là một chức năng liên kết bàn phím

Nếu bạn chỉ định một giá trị số khác 0, thì giá trị này sẽ đợi trong một phần nghìn giây đã chỉ định cho bất kỳ sự kiện bàn phím nào. Nếu bạn nhấn bất kỳ phím nào, thì chương trình sẽ tiếp tục. Nếu bạn chỉ định 0 làm giá trị, thì nó sẽ đợi vô thời hạn

destroyAllWindows[] sẽ hủy tất cả các cửa sổ đã tạo

Để hủy các cửa sổ cụ thể, bạn có thể sử dụng destroyWindow[] mà bạn sẽ chuyển tên cửa sổ vào đó

import cv2
image_cv2= cv2.imread[r'\dogs-v-cats\dog.1.png']
cv2.imshow["Dog Image using OpenCV", image_cv2]

cv2.waitKey[6000]
cv2.destroyWindow["Dog Image using OpenCV"]

Lưu hình ảnh bằng OpenCV

result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]

imwrite[] lưu tệp hình ảnh vào đường dẫn đã chỉ định. Tham số đầu tiên là đường dẫn mà bạn muốn lưu tệp và tham số thứ hai là hình ảnh sẽ được lưu

Tải hình ảnh bằng matplotlib

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]

imread[] của matplotlib đọc tệp hình ảnh từ đường dẫn đã chỉ định vào một mảng. Tham số thứ hai là tùy chọn và chỉ định định dạng của tệp như 'JPEG' hoặc "PNG". Giá trị mặc định là 'PNG. ’

imshow[] của matplotlib hiển thị mảng dữ liệu dưới dạng hình ảnh

bạn cũng có thể sử dụng plt. show[] để hiển thị hình ảnh

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg’, “JPG”]
imgplot=plt.imshow[image_mp]
plt.show[]

Ở cấp độ rất cơ bản, hầu hết mọi tệp nhị phân đều chứa một vài điểm đánh dấu [hoặc tiêu đề]. Bạn có thể coi những điểm đánh dấu này giống như những dấu trang. Chúng rất quan trọng để hiểu ý nghĩa của tệp và được các chương trình như

10 10 10 10 10 10 10
9 [trên Mac/Linux] sử dụng để cho chúng tôi biết chi tiết về tệp. Các điểm đánh dấu này xác định nơi lưu trữ một số thông tin cụ thể trong tệp. Hầu hết các điểm đánh dấu được theo sau bởi thông tin
7 10
0 cho đoạn đánh dấu cụ thể. Điều này cho chúng tôi biết đoạn cụ thể đó dài bao lâu

Bắt đầu tệp & Kết thúc tệp

Điểm đánh dấu đầu tiên mà chúng tôi quan tâm là

7 10
1. Nó cho chúng ta biết rằng đây là điểm bắt đầu của hình ảnh. Nếu chúng tôi không nhìn thấy nó, chúng tôi có thể cho rằng đây là một số tệp khác. Một điểm đánh dấu quan trọng không kém khác là
7 10
2. Nó cho chúng tôi biết rằng chúng tôi đã đến cuối tệp hình ảnh. Mọi điểm đánh dấu, ngoại trừ
7 10
3 đến
7 10
4 và
7 10
5, ngay sau đó là một bộ xác định độ dài sẽ cung cấp cho bạn độ dài của đoạn đánh dấu đó. Đối với các điểm đánh dấu bắt đầu và kết thúc tệp hình ảnh, chúng sẽ luôn dài hai byte mỗi dấu

Trong suốt hướng dẫn này, chúng tôi sẽ làm việc với hình ảnh này

Hãy viết một số mã để xác định các điểm đánh dấu này

result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
2

Chúng tôi đang sử dụng cấu trúc để giải nén byte dữ liệu hình ảnh.

7 10
6 yêu cầu
7 10
7 coi dữ liệu là big-endian và thuộc loại
7 10
8. Dữ liệu trong JPEG được lưu trữ ở định dạng big-endian. Chỉ dữ liệu EXIF ​​​​có thể ở dạng cuối nhỏ [mặc dù nó không phổ biến]. Và một đoạn ngắn có kích thước 2, vì vậy chúng tôi cung cấp
7 10
9 hai byte từ
result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
70 của chúng tôi. Bạn có thể tự hỏi làm thế nào chúng tôi biết đó là một
result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
71. Chà, chúng tôi biết rằng các điểm đánh dấu trong JPEG là 4 chữ số hex.
result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
72. Một chữ số hex bằng 4 bit [1⁄2 byte] nên 4 chữ số hex sẽ bằng 2 byte và một chữ số ngắn bằng 2 byte

Phần Bắt đầu quét ngay sau đó là dữ liệu quét hình ảnh và dữ liệu quét hình ảnh đó không có độ dài được chỉ định. Nó tiếp tục cho đến khi tìm thấy điểm đánh dấu “cuối tệp”, vì vậy hiện tại chúng tôi đang “tìm kiếm” điểm đánh dấu EOF theo cách thủ công bất cứ khi nào chúng tôi nhìn thấy điểm đánh dấu SOC

Bây giờ chúng ta đã có khung cơ bản, hãy tiếp tục và tìm hiểu xem phần còn lại của dữ liệu hình ảnh chứa gì. Trước tiên chúng ta sẽ xem qua một số lý thuyết cần thiết và sau đó bắt đầu viết mã

Mã hóa JPEG

Trước tiên tôi sẽ giải thích một số khái niệm cơ bản và kỹ thuật mã hóa được sử dụng bởi JPEG và sau đó giải mã sẽ diễn ra một cách tự nhiên từ đó ngược lại với nó. Theo kinh nghiệm của tôi, việc trực tiếp cố gắng hiểu ý nghĩa của việc giải mã là hơi khó

Mặc dù hình ảnh dưới đây không có nhiều ý nghĩa đối với bạn ngay bây giờ, nhưng nó sẽ cung cấp cho bạn một số mỏ neo để bám vào trong khi chúng tôi thực hiện toàn bộ quá trình mã hóa/giải mã. Nó cho thấy các bước liên quan đến quá trình mã hóa JPEG. [src]

Không gian màu JPEG

Theo thông số JPEG [ISO/IEC 10918-6. 2013 [E], mục 6. 1]

  • Hình ảnh được mã hóa chỉ với một thành phần được coi là dữ liệu thang độ xám trong đó 0 là màu đen và 255 là màu trắng
  • Hình ảnh được mã hóa với ba thành phần được coi là dữ liệu RGB được mã hóa thành YCbCr trừ khi hình ảnh chứa đoạn nhãn APP14 như được chỉ định trong 6. 5. 3, trong trường hợp đó, mã hóa màu được coi là RGB hoặc YCbCr theo dữ liệu ứng dụng của đoạn đánh dấu APP14. Mối quan hệ giữa RGB và YCbCr được xác định như được chỉ định trong Rec. ITU-T T. 871. ISO/IEC 10918-5
  • Hình ảnh được mã hóa với bốn thành phần được coi là CMYK, với [0,0,0,0] biểu thị màu trắng trừ khi hình ảnh chứa đoạn đánh dấu APP14 như được chỉ định trong 6. 5. 3, trong trường hợp đó, mã hóa màu được coi là CMYK hoặc YCCK theo dữ liệu ứng dụng của đoạn đánh dấu APP14. Mối quan hệ giữa CMYK và YCCK được xác định như quy định tại khoản 7

Hầu hết các triển khai thuật toán JPEG đều sử dụng độ chói và sắc độ [mã hóa YUV] thay vì RGB. Điều này cực kỳ hữu ích trong JPEG vì mắt người khá tệ khi nhìn thấy sự thay đổi độ sáng ở tần số cao trên một khu vực nhỏ, vì vậy về cơ bản chúng ta có thể giảm lượng tần số và mắt người sẽ không thể nhận ra sự khác biệt. Kết quả?

Giống như mỗi pixel trong không gian màu RGB được tạo thành từ 3 byte dữ liệu màu [Đỏ, Xanh lục, Xanh lam], mỗi pixel trong YUV cũng sử dụng 3 byte nhưng mỗi byte thể hiện hơi khác nhau. Thành phần Y xác định độ sáng của màu [còn được gọi là độ chói hoặc độ sáng], trong khi thành phần U và V xác định màu [còn được gọi là sắc độ]. Thành phần U đề cập đến lượng màu xanh lam và thành phần V đề cập đến lượng màu đỏ

Định dạng màu này được phát minh khi TV màu không quá phổ biến và các kỹ sư muốn sử dụng một định dạng mã hóa hình ảnh cho cả TV màu và đen trắng. YUV có thể được hiển thị an toàn trên TV đen trắng nếu không có màu. Bạn có thể đọc thêm về lịch sử của nó trên Wikipedia

Biến đổi Cosine rời rạc và lượng tử hóa

JPEG chuyển đổi một hình ảnh thành các khối pixel 8x8 [được gọi là MCU hoặc Đơn vị mã hóa tối thiểu], thay đổi phạm vi giá trị của pixel để chúng tập trung vào 0 và sau đó áp dụng Biến đổi Cosine rời rạc cho từng khối và sau đó sử dụng lượng tử hóa để nén . Hãy hiểu rõ hơn về ý nghĩa của tất cả các thuật ngữ này

Biến đổi Cosine rời rạc là một phương pháp để chuyển đổi các điểm dữ liệu rời rạc thành sự kết hợp của các sóng cosine. Có vẻ khá vô ích khi dành thời gian chuyển đổi một hình ảnh thành một loạt cosin nhưng sẽ hợp lý khi chúng ta hiểu DCT kết hợp với cách hoạt động của bước tiếp theo. Trong JPEG, DCT sẽ lấy một khối hình ảnh 8x8 và cho chúng tôi biết cách tái tạo nó bằng cách sử dụng ma trận hàm cosine 8x8. Đọc thêm tại đây]

Ma trận 8x8 của các hàm cosin trông như thế này

Chúng tôi áp dụng DCT cho từng thành phần của pixel một cách riêng biệt. Đầu ra của việc áp dụng DCT là một ma trận hệ số 8x8 cho chúng ta biết mỗi hàm cosin [trong tổng số 64 hàm] đóng góp bao nhiêu vào ma trận đầu vào 8x8. Ma trận hệ số của DCT thường chứa các giá trị lớn hơn ở góc trên cùng bên trái của ma trận hệ số và các giá trị nhỏ hơn ở góc dưới cùng bên phải. Góc trên cùng bên trái biểu thị hàm cosin tần số thấp nhất và góc dưới bên phải biểu thị hàm cosin tần số cao nhất

Điều này cho chúng ta biết rằng hầu hết các hình ảnh chứa một lượng lớn thông tin tần số thấp và một lượng nhỏ thông tin tần số cao. Nếu chúng ta biến các thành phần dưới cùng bên phải của mỗi ma trận DCT thành 0, thì hình ảnh thu được sẽ vẫn giống như vậy bởi vì, như tôi đã đề cập, con người rất tệ trong việc quan sát các thay đổi tần số cao. Đây chính xác là những gì chúng tôi làm trong bước tiếp theo

Tôi tìm thấy một video tuyệt vời về chủ đề này. Xem nó nếu DCT không có quá nhiều ý nghĩa

Tất cả chúng ta đều đã nghe nói rằng JPEG là một thuật toán nén bị mất dữ liệu nhưng cho đến nay chúng tôi vẫn chưa thực hiện bất kỳ điều gì làm mất dữ liệu. Chúng tôi chỉ chuyển đổi các khối 8x8 của các thành phần YUV thành các khối hàm cosine 8x8 mà không làm mất thông tin. Phần mất dữ liệu xuất hiện trong bước lượng tử hóa

Lượng tử hóa là một quá trình trong đó chúng tôi lấy một vài giá trị trong một phạm vi cụ thể và biến chúng thành một giá trị riêng biệt. Đối với trường hợp của chúng tôi, đây chỉ là một cái tên ưa thích để chuyển đổi các hệ số tần số cao hơn trong ma trận đầu ra DCT thành 0. Khi bạn lưu ảnh bằng JPEG, hầu hết các chương trình chỉnh sửa ảnh đều hỏi bạn cần nén bao nhiêu. Tỷ lệ phần trăm bạn cung cấp ở đó ảnh hưởng đến mức độ lượng tử hóa được áp dụng và lượng thông tin tần số cao hơn bị mất. Đây là nơi áp dụng nén mất dữ liệu. Khi bạn mất thông tin tần số cao, bạn không thể tạo lại hình ảnh gốc chính xác từ hình ảnh JPEG thu được

Tùy thuộc vào mức độ nén được yêu cầu, một số ma trận lượng tử hóa phổ biến được sử dụng [thực tế thú vị. Hầu hết các nhà cung cấp đều có bằng sáng chế về xây dựng bảng lượng tử hóa]. Chúng tôi chia phần tử ma trận hệ số DCT với ma trận lượng tử hóa, làm tròn kết quả thành một số nguyên và nhận ma trận lượng tử hóa. Hãy đi qua một ví dụ

Nếu bạn có ma trận DCT này

Ma trận lượng tử hóa [phổ biến] này

Sau đó, ma trận lượng tử hóa kết quả sẽ là thế này

Mặc dù con người không thể nhìn thấy thông tin tần số cao, nhưng nếu bạn loại bỏ quá nhiều thông tin khỏi khối hình ảnh 8x8, hình ảnh tổng thể sẽ trông có vẻ khối. Trong ma trận lượng tử hóa này, giá trị đầu tiên được gọi là giá trị DC và các giá trị còn lại là giá trị AC. Nếu chúng tôi lấy các giá trị DC từ tất cả các ma trận được lượng tử hóa và tạo một hình ảnh mới, về cơ bản chúng tôi sẽ có một hình thu nhỏ với độ phân giải 1/8 của hình ảnh gốc

Cũng cần lưu ý rằng vì chúng tôi áp dụng lượng tử hóa trong khi giải mã, chúng tôi sẽ phải đảm bảo màu sắc nằm trong phạm vi [0,255]. Nếu chúng nằm ngoài phạm vi này, chúng tôi sẽ phải tự kẹp chúng vào phạm vi này

ngoằn ngoèo

Sau khi lượng tử hóa, JPEG sử dụng mã hóa zig-zag để chuyển đổi ma trận thành 1D [img src]

Hãy tưởng tượng chúng ta có ma trận lượng tử hóa này

Đầu ra của mã hóa zig-zag sẽ là thế này

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
0

Mã hóa này được ưu tiên vì hầu hết thông tin tần số thấp [quan trọng nhất] được lưu trữ ở đầu ma trận sau khi lượng tử hóa và mã hóa zig-zag lưu trữ tất cả thông tin đó ở đầu ma trận 1D. Điều này hữu ích cho quá trình nén xảy ra trong bước tiếp theo

Độ dài chạy và mã hóa Delta

Mã hóa độ dài chạy được sử dụng để nén dữ liệu lặp lại. Khi kết thúc quá trình mã hóa zig-zag, chúng ta đã thấy hầu hết các mảng 1D được mã hóa zig-zag đều có rất nhiều số 0 ở cuối. Mã hóa độ dài chạy cho phép chúng tôi lấy lại tất cả dung lượng bị lãng phí đó và sử dụng ít byte hơn để biểu thị tất cả các số 0 đó. Hãy tưởng tượng bạn có một số dữ liệu như thế này

10 10 10 10 10 10 10

Mã hóa độ dài chạy sẽ chuyển đổi nó thành

7 10

Chúng tôi đã có thể nén thành công 7 byte dữ liệu thành chỉ 2 byte

Mã hóa delta là một kỹ thuật được sử dụng để biểu diễn một byte so với byte trước nó. Nó dễ hiểu hơn với một ví dụ. Giả sử bạn có dữ liệu sau

result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
7

Bạn có thể sử dụng mã hóa delta để lưu trữ nó như thế này

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
4

Trong JPEG, mọi giá trị DC trong ma trận hệ số DCT được mã hóa delta tương ứng với giá trị DC trước nó. Điều này có nghĩa là nếu bạn thay đổi hệ số DCT đầu tiên của hình ảnh, toàn bộ hình ảnh sẽ bị hỏng nhưng nếu bạn sửa đổi giá trị đầu tiên của ma trận DCT cuối cùng, thì chỉ một phần rất nhỏ của hình ảnh sẽ bị ảnh hưởng. Điều này rất hữu ích vì giá trị DC đầu tiên trong hình ảnh của bạn thường đa dạng nhất và bằng cách áp dụng mã hóa Delta, chúng tôi đưa các giá trị DC còn lại về gần 0 và điều đó dẫn đến khả năng nén tốt hơn trong bước tiếp theo của Mã hóa Huffman

Mã hóa Huffman

Mã hóa Huffman là một phương pháp nén thông tin không mất dữ liệu. Huffman đã từng tự hỏi: “Số lượng bit nhỏ nhất mà tôi có thể sử dụng để lưu trữ một đoạn văn bản tùy ý là bao nhiêu?”. Định dạng mã hóa này là câu trả lời của anh ấy. Hãy tưởng tượng bạn phải lưu trữ văn bản này

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
5

Trong một kịch bản bình thường, mỗi ký tự sẽ chiếm 1 byte dung lượng

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
6

Điều này dựa trên ASCII để ánh xạ nhị phân. Nhưng nếu chúng ta có thể đưa ra một ánh xạ tùy chỉnh thì sao?

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
7

Bây giờ chúng ta có thể lưu trữ cùng một văn bản bằng cách sử dụng ít bit hơn

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
8

Điều này là tốt và tốt nhưng nếu chúng ta muốn chiếm ít không gian hơn thì sao?

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
00

Mã hóa Huffman cho phép chúng tôi sử dụng loại ánh xạ có độ dài thay đổi này. Nó lấy một số dữ liệu đầu vào, ánh xạ các ký tự thường xuyên nhất thành các mẫu bit nhỏ hơn và các ký tự ít thường xuyên nhất thành các mẫu bit lớn hơn và cuối cùng tổ chức ánh xạ thành cây nhị phân. Trong JPEG, chúng tôi lưu trữ thông tin DCT [Biến đổi Cosine rời rạc] bằng cách sử dụng mã hóa Huffman. Hãy nhớ rằng tôi đã nói với bạn rằng việc sử dụng mã hóa delta cho các giá trị DC sẽ giúp ích cho Mã hóa Huffman? . Sau khi mã hóa delta, chúng tôi kết thúc với ít “ký tự” hơn để lập bản đồ và tổng kích thước của cây Huffman của chúng tôi bị giảm

Tom Scott có một video tuyệt vời với hình ảnh động về cách hoạt động của mã hóa Huffman nói chung. Hãy xem nó trước khi tiếp tục

Một JPEG chứa tối đa 4 bảng Huffman và những bảng này được lưu trữ trong phần “Xác định bảng Huffman” [bắt đầu bằng

result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
73]. Các hệ số DCT được lưu trữ trong 2 bảng Huffman khác nhau. Một cái chỉ chứa các giá trị DC từ các bảng zig-zag và cái kia chứa các giá trị AC từ các bảng zig-zag. Điều này có nghĩa là trong quá trình giải mã, chúng ta sẽ phải hợp nhất các giá trị DC và AC từ hai ma trận riêng biệt. Thông tin DCT cho kênh độ chói và màu sắc được lưu trữ riêng biệt, vì vậy chúng tôi có 2 bộ thông tin DC và 2 bộ thông tin AC, cung cấp cho chúng tôi tổng cộng 4 bảng Huffman

Trong một hình ảnh thang độ xám, chúng tôi sẽ chỉ có 2 bảng Huffman [1 cho DC và 1 cho AC] vì chúng tôi không quan tâm đến màu sắc. Như bạn có thể hình dung, 2 hình ảnh có thể có các bảng Huffman rất khác nhau, vì vậy điều quan trọng là phải lưu trữ các bảng này bên trong mỗi JPEG

Vì vậy, chúng tôi biết các chi tiết cơ bản về những gì hình ảnh JPEG chứa. Hãy bắt đầu với việc giải mã

giải mã JPEG

Chúng ta có thể chia quá trình giải mã thành nhiều bước

  1. Trích xuất các bảng Huffman và giải mã các bit
  2. Trích xuất các hệ số DCT bằng cách hoàn tác mã hóa độ dài chạy và mã hóa delta
  3. Sử dụng các hệ số DCT để kết hợp các sóng cosin và tạo lại các giá trị pixel cho mỗi khối 8x8
  4. Chuyển đổi YCbCr sang RGB cho từng pixel
  5. Hiển thị hình ảnh RGB kết quả

Chuẩn JPEG hỗ trợ 4 định dạng nén

  • đường cơ sở
  • tuần tự mở rộng
  • Cấp tiến
  • Không mất mát

Chúng tôi sẽ làm việc với nén Baseline và theo tiêu chuẩn, đường cơ sở sẽ chứa một loạt các khối 8x8 ngay cạnh nhau. Các định dạng nén khác bố trí dữ liệu hơi khác một chút. Chỉ để tham khảo, tôi đã tô màu các phân đoạn khác nhau trong nội dung hex của hình ảnh chúng tôi đang sử dụng. Cái này nó thì trông như thế nào

Trích xuất các bảng Huffman

Chúng ta đã biết rằng một JPEG chứa 4 bảng Huffman. Đây là bước cuối cùng trong quy trình mã hóa, vì vậy đây phải là bước đầu tiên trong quy trình giải mã. Mỗi phần DHT chứa các thông tin sau

FieldSizeDescriptionMarker Identifier2 bytes0xff, 0xc4 để xác định DHT markerLength2 bytesĐiều này chỉ định độ dài của bảng HuffmanThông tin HT1 bytebit 0. 3. số HT [0. 3, nếu không thì lỗi]
bit 4. loại HT, 0 = bảng DC, 1 = bảng AC
bit 5. 7. không được sử dụng, phải là 0Số ký hiệu16 byteSố ký hiệu có mã độ dài 1. 16, tổng[n] của các byte này là tổng số mã, phải là

Giả sử bạn có một bảng DH tương tự như thế này [src]

Ký hiệu Mã HuffmanĐộ dài mã a002b0103c0113d1003e1013f1103g11104h111105i1111106j11111107k111111108l1111111109

Nó sẽ được lưu trữ trong tệp JFIF đại khái như thế này [chúng sẽ được lưu trữ ở dạng nhị phân. Tôi đang sử dụng ASCII chỉ cho mục đích minh họa]

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
01

0 có nghĩa là không có mã Huffman có độ dài 1. 1 nghĩa là có 1 mã Huffman độ dài 2. Và như thế. Luôn có dữ liệu độ dài 16 byte trong phần DHT ngay sau thông tin lớp và ID. Hãy viết một số mã để trích xuất độ dài và các phần tử trong DHT

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
02

Nếu bạn chạy mã, nó sẽ tạo ra đầu ra sau

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
03

Ngọt. Chúng tôi có độ dài và các yếu tố. Bây giờ chúng ta cần tạo một lớp bảng Huffman tùy chỉnh để chúng ta có thể tạo lại cây nhị phân từ các phần tử và độ dài này. Tôi xấu hổ sao chép mã này từ đây

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
04

result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
74 lấy độ dài và phần tử, lặp qua tất cả các phần tử và đặt chúng vào danh sách
result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
75. Danh sách này chứa các danh sách lồng nhau và đại diện cho một cây nhị phân. Bạn có thể đọc trực tuyến cách thức hoạt động của Cây Huffman và cách tạo cấu trúc dữ liệu cây Huffman của riêng bạn bằng Python. Đối với DHT đầu tiên của chúng tôi [sử dụng hình ảnh tôi đã liên kết khi bắt đầu hướng dẫn này], chúng tôi có các dữ liệu, độ dài và thành phần sau

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
05

Sau khi gọi

result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
74 về điều này, danh sách
result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
75 sẽ chứa dữ liệu này

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
06

result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
78 cũng chứa phương thức
result=cv2.imwrite[r'\dogs-v-cats\dog.100.png’, image_cv2]
if result==True:
print[“File saved successfully”]
else:
print[“Error in saving file”]
79 duyệt cây cho chúng ta và trả lại cho chúng ta các bit đã giải mã bằng bảng Huffman. Phương pháp này mong đợi một dòng bit làm đầu vào. Dòng bit chỉ là biểu diễn nhị phân của dữ liệu. Ví dụ: dòng bit điển hình của
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
40 sẽ là
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
41. Trước tiên, chúng tôi chuyển đổi từng ký tự thành mã ASCII của nó và sau đó chuyển đổi mã ASCII đó thành nhị phân. Hãy tạo một lớp tùy chỉnh cho phép chúng ta chuyển đổi một chuỗi thành bit và đọc từng bit một. Đây là cách chúng tôi sẽ thực hiện nó

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
07

Chúng tôi cung cấp cho lớp này một số dữ liệu nhị phân trong khi khởi tạo nó và sau đó sử dụng các phương thức

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
42 và
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
43 để đọc nó

Giải mã bảng lượng tử hóa

Phần Xác định bảng lượng tử chứa dữ liệu sau

FieldSizeDescriptionMarker Identifier2 byte0xff, 0xdb xác định DQTLength2 byteĐiều này cho biết độ dài của QT. Thông tin QT1 bytebit 0. 3. số lượng QT [0. 3, nếu không thì lỗi] bit 4. 7. độ chính xác của QT, 0 = 8 bit, nếu không thì 16 bitBytesn byteĐiều này mang lại giá trị QT, n = 64*[độ chính xác+1]

Theo chuẩn JPEG, có 2 bảng lượng tử hóa mặc định trong một ảnh JPEG. Một cho độ chói và một cho sắc độ. Các bảng này bắt đầu từ điểm đánh dấu

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
44. Trong mã ban đầu chúng tôi đã viết, chúng tôi đã thấy rằng đầu ra chứa hai điểm đánh dấu
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
44. Hãy mở rộng mã mà chúng tôi đã có và thêm khả năng giải mã các bảng lượng tử hóa

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
08

Chúng tôi đã làm một vài điều ở đây. Đầu tiên, tôi định nghĩa một phương thức

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
46. Nó chỉ là một phương pháp tiện dụng để giải mã một số lượng byte khác nhau từ dữ liệu nhị phân. Tôi đã thay thế một số mã trong phương thức
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
47 để sử dụng chức năng mới này. Sau đó, tôi đã định nghĩa phương thức
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
48. Phương pháp này chỉ cần đọc tiêu đề của phần Bảng lượng tử hóa và sau đó nối thêm dữ liệu lượng tử hóa vào từ điển với giá trị tiêu đề là khóa. Giá trị tiêu đề sẽ là 0 cho độ chói và 1 cho sắc độ. Mỗi phần Bảng lượng tử hóa trong JFIF chứa 64 byte dữ liệu QT [đối với ma trận lượng tử hóa 8x8 của chúng tôi]

Nếu chúng ta in ma trận lượng tử hóa cho hình ảnh của mình. Họ sẽ trông như thế này

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
09

Giải mã bắt đầu khung hình

Phần Bắt đầu của Khung chứa các thông tin sau [src]

FieldSizeDescriptionĐịnh danh Marker2 byte0xff, 0xc0 để xác định điểm đánh dấu SOF0Độ dài2 byteGiá trị này bằng 8 + thành phần*3 giá trịĐộ chính xác của dữ liệu1 byteĐây là bit/mẫu, thường là 8 [12 và 16 không được hầu hết các phần mềm hỗ trợ]. Chiều cao hình ảnh2 byteĐây phải là > 0Chiều rộng hình ảnh2 byteĐây phải là > 0Số lượng thành phần1 byteThông thường 1 = thang màu xám, 3 = màu YcbCr hoặc YIQMỗi thành phần3 byteĐọc từng dữ liệu thành phần gồm 3 byte. Nó chứa, [Id thành phần[1byte][1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q], hệ số lấy mẫu [1byte] [bit 0-3 dọc. , 4-7 ngang. ], số bảng lượng tử hóa [1 byte]]

Trong số dữ liệu này, chúng tôi chỉ quan tâm đến một số điều. Chúng tôi sẽ trích xuất chiều rộng và chiều cao của hình ảnh và số bảng lượng tử hóa của từng thành phần. Chiều rộng và chiều cao sẽ được sử dụng khi chúng tôi bắt đầu giải mã các bản quét hình ảnh thực tế từ phần Bắt đầu quét. Vì chúng ta sẽ chủ yếu làm việc với ảnh YCbCr, nên chúng ta có thể mong đợi số lượng thành phần bằng 3 và loại thành phần lần lượt bằng 1, 2 và 3. Hãy viết một số mã để giải mã dữ liệu này

10 10 10 10 10 10 10
0

Chúng tôi đã thêm thuộc tính danh sách

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
49 vào lớp JPEG của mình và giới thiệu phương thức
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
50. Phương pháp
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
50 giải mã dữ liệu cần thiết từ phần SOF và đặt số bảng lượng tử hóa của từng thành phần trong danh sách
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
49. Chúng tôi sẽ sử dụng ánh xạ này khi chúng tôi bắt đầu đọc phần Bắt đầu quét. Đây là giao diện của
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
49 đối với hình ảnh của chúng tôi

10 10 10 10 10 10 10
1

Giải mã Bắt đầu quét

Ngọt. Chúng ta chỉ còn một phần nữa để giải mã. Đây là phần chính của hình ảnh JPEG và chứa dữ liệu "hình ảnh" thực tế. Đây cũng là bước phức tạp nhất. Mọi thứ khác mà chúng tôi đã giải mã cho đến nay có thể được coi là tạo bản đồ để giúp chúng tôi điều hướng và giải mã hình ảnh thực tế. Phần này chứa chính hình ảnh thực tế [mặc dù ở dạng được mã hóa]. Chúng tôi sẽ đọc phần này và sử dụng dữ liệu chúng tôi đã giải mã để hiểu ý nghĩa của hình ảnh

Tất cả các điểm đánh dấu chúng tôi đã thấy cho đến nay đều bắt đầu bằng

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
54.
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
54 cũng có thể là một phần của dữ liệu quét hình ảnh nhưng nếu
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
54 có trong dữ liệu quét thì nó sẽ luôn đứng trước ________ 257. Đây là điều mà bộ mã hóa JPEG thực hiện tự động và được gọi là nhồi byte. Nhiệm vụ của người giải mã là loại bỏ thủ tục tố tụng này
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
57. Hãy bắt đầu phương thức giải mã SOS với chức năng này và loại bỏ
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
57 nếu nó hiện diện. Trong hình ảnh mẫu tôi đang sử dụng, chúng tôi không có
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
54 trong dữ liệu quét hình ảnh nhưng nó vẫn là một bổ sung hữu ích

10 10 10 10 10 10 10
2

Trước đây, tôi đã tìm kiếm thủ công đến cuối tệp bất cứ khi nào tôi gặp điểm đánh dấu

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
61 nhưng bây giờ chúng tôi đã có sẵn công cụ cần thiết để duyệt qua toàn bộ tệp theo thứ tự có hệ thống, tôi đã chuyển điều kiện đánh dấu vào bên trong mệnh đề
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
62. Hàm
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
63 chỉ bị ngắt bất cứ khi nào nó quan sát thấy thứ gì đó không phải là
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
57 sau
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
54. Do đó, nó sẽ thoát ra khỏi vòng lặp khi gặp phải
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
66 và bằng cách đó chúng ta có thể tìm kiếm đến cuối tệp một cách an toàn mà không gặp bất kỳ sự cố nào. Nếu bạn chạy mã này ngay bây giờ, sẽ không có gì mới xuất ra thiết bị đầu cuối

Nhớ lại rằng JPEG đã chia hình ảnh thành ma trận 8x8. Bước tiếp theo đối với chúng tôi là chuyển đổi dữ liệu quét hình ảnh của chúng tôi thành luồng bit và xử lý luồng theo khối dữ liệu 8x8. Hãy thêm một số mã vào lớp của chúng tôi

10 10 10 10 10 10 10
3

Chúng tôi bắt đầu bằng cách chuyển đổi dữ liệu quét của mình thành luồng bit. Sau đó, chúng tôi khởi tạo

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
67,
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
68,
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
69 thành 0. Những điều này là bắt buộc vì hãy nhớ rằng chúng ta đã nói về cách phần tử DC trong ma trận lượng tử hóa [phần tử đầu tiên của ma trận] được mã hóa delta so với phần tử DC trước đó?

Vòng lặp

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
70 có vẻ hơi thú vị.
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
71 cho biết chúng ta có thể chia chiều cao cho 8 bao nhiêu lần. Điều tương tự cũng xảy ra với
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
72. Tóm lại, điều này cho chúng ta biết hình ảnh được chia thành bao nhiêu ma trận 8x8

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
73 sẽ lấy bảng lượng tử hóa và một số tham số bổ sung, tạo Ma trận biến đổi Cosine rời rạc nghịch đảo và cung cấp cho chúng ta ma trận Y, Cr và Cb. Việc chuyển đổi thực tế các ma trận này thành RGB sẽ xảy ra trong hàm
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
74

Trước tiên, hãy tạo lớp IDCT của chúng ta và sau đó chúng ta có thể bắt đầu bổ sung phương thức

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
73

10 10 10 10 10 10 10
4

Hãy cố gắng hiểu lớp IDCT này từng bước. Khi chúng tôi trích xuất MCU từ JPEG, thuộc tính

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
76 của lớp này sẽ lưu trữ nó. Sau đó, chúng tôi sẽ sắp xếp lại ma trận MCU bằng cách hoàn tác mã hóa ngoằn ngoèo thông qua phương pháp
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
77. Cuối cùng, chúng tôi sẽ hoàn tác Biến đổi Cosine rời rạc bằng cách gọi phương thức
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
78

Nếu bạn còn nhớ, bảng Discrete Cosine là cố định. Cách tính toán thực tế cho một DCT hoạt động nằm ngoài phạm vi của hướng dẫn này vì nó thiên về toán hơn là lập trình. Chúng ta có thể lưu trữ bảng này dưới dạng một biến toàn cục và sau đó truy vấn giá trị đó dựa trên các cặp x, y. Tôi quyết định đặt bảng và tính toán của nó trong lớp

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
79 cho mục đích dễ đọc. Mỗi phần tử của ma trận MCU được sắp xếp lại được nhân với các giá trị của
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
80 và cuối cùng chúng tôi lấy lại các giá trị Y, Cr và Cb

Điều này sẽ có ý nghĩa hơn khi chúng ta viết ra phương thức

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
73

Nếu bạn sửa đổi bảng ngoằn ngoèo thành một cái gì đó như thế này

10 10 10 10 10 10 10
5

Bạn sẽ có đầu ra sau [chú ý các đồ tạo tác nhỏ]

Và nếu bạn dũng cảm, bạn có thể sửa đổi bảng ngoằn ngoèo hơn nữa

10 10 10 10 10 10 10
6

Nó sẽ dẫn đến đầu ra này

Bây giờ, hãy kết thúc phương pháp

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
73 của chúng ta

10 10 10 10 10 10 10
7

Chúng tôi bắt đầu bằng cách tạo một lớp Biến đổi Cosine rời rạc nghịch đảo [

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
83]. Sau đó, chúng tôi đọc trong luồng bit và giải mã nó bằng bảng Huffman của chúng tôi

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
84 và
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
85 lần lượt đề cập đến các bảng DC về độ chói và sắc độ và
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
86 và
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
87 lần lượt đề cập đến các bảng AC về độ chói và sắc độ

Sau khi chúng tôi giải mã luồng bit, chúng tôi trích xuất hệ số DC được mã hóa delta mới bằng cách sử dụng hàm

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
88 và thêm
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
89 vào nó để có được hệ số DC được giải mã delta

Sau đó, chúng tôi lặp lại quy trình giải mã tương tự nhưng đối với các giá trị AC trong ma trận lượng tử hóa. Giá trị mã của

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
000 gợi ý rằng chúng tôi đã gặp phải điểm đánh dấu Kết thúc Khối [EOB] và chúng tôi cần dừng. Hơn nữa, phần đầu tiên của bảng lượng tử AC cho chúng ta biết chúng ta có bao nhiêu số 0 đứng đầu. Hãy nhớ mã hóa độ dài chạy mà chúng ta đã nói trong phần đầu tiên? . Chúng tôi giải mã mã hóa độ dài chạy và bỏ qua nhiều bit đó. Tất cả các bit bị bỏ qua đều được đặt thành 0 hoàn toàn trong lớp
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
79

Khi chúng tôi đã giải mã các giá trị DC và AC cho một MCU, chúng tôi sắp xếp lại MCU và hoàn tác mã hóa ngoằn ngoèo bằng cách gọi

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
77 và sau đó chúng tôi thực hiện đảo ngược DCT trên MCU đã giải mã

Phương thức

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
73 sẽ trả về ma trận DCT nghịch đảo và giá trị của hệ số DC. Hãy nhớ rằng, ma trận DCT nghịch đảo này chỉ dành cho một ma trận MCU [Đơn vị được mã hóa tối thiểu] 8x8 nhỏ. Chúng tôi sẽ làm điều này cho tất cả các MCU riêng lẻ trong toàn bộ tệp hình ảnh

Hiển thị hình ảnh trên màn hình

Hãy sửa đổi mã của chúng ta một chút và tạo một Tkinter Canvas và vẽ từng MCU sau khi giải mã nó theo phương thức

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
004

10 10 10 10 10 10 10
8

Hãy bắt đầu với các hàm

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
005 và
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
006.
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
005 nhận các giá trị Y, Cr và Cb, sử dụng công thức để chuyển đổi các giá trị này thành các giá trị RGB của chúng, sau đó xuất các giá trị RGB được kẹp. Bạn có thể thắc mắc tại sao chúng tôi lại thêm 128 vào các giá trị RGB. Nếu bạn còn nhớ, trước khi máy nén JPEG áp dụng DCT trên MCU, nó sẽ trừ 128 khỏi các giá trị màu. Nếu màu ban đầu nằm trong phạm vi [0,255], JPEG sẽ đặt chúng vào phạm vi [-128,+128]. Vì vậy, chúng tôi phải hoàn tác hiệu ứng đó khi giải mã JPEG và đó là lý do tại sao chúng tôi thêm 128 vào RGB. Đối với
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
006, trong quá trình giải nén, giá trị đầu ra có thể vượt quá [0,255] nên chúng tôi kẹp chúng trong khoảng [0,255]

Trong phương thức

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
74, chúng tôi lặp qua từng ma trận Y, Cr và Cb được giải mã 8x8 và chuyển đổi từng phần tử của ma trận 8x8 thành các giá trị RGB. Sau khi chuyển đổi, chúng tôi vẽ từng pixel trên Tkinter
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
010 bằng phương pháp
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
image_mp= mpimg.imread[r'\dogs-v-cats\dog.1.jpg']
imgplot=plt.imshow[image_mp]
plt.plot[]
011. Bạn có thể tìm thấy mã hoàn chỉnh trên GitHub. Bây giờ nếu bạn chạy mã này, khuôn mặt của tôi sẽ hiển thị trên màn hình của bạn 😄

Phần kết luận

Oh Boy. Ai có thể nghĩ rằng nó sẽ mất 6000 từ + lời giải thích để hiển thị khuôn mặt của tôi trên màn hình. Tôi ngạc nhiên bởi sự thông minh của một số nhà phát minh thuật toán này. Tôi hy vọng bạn thích bài viết này nhiều như tôi thích viết nó. Tôi đã học được rất nhiều điều khi viết bộ giải mã này. Tôi chưa bao giờ nhận ra có bao nhiêu phép toán phức tạp đi vào quá trình mã hóa một hình ảnh JPEG đơn giản. Tôi có thể làm việc với hình ảnh PNG tiếp theo và thử viết bộ giải mã cho hình ảnh PNG. Bạn cũng nên thử viết bộ giải mã cho PNG [hoặc một số định dạng khác]. Tôi chắc chắn rằng nó sẽ liên quan đến rất nhiều việc học và thậm chí còn thú vị hơn nữa 😅

Dù bằng cách nào, bây giờ tôi mệt mỏi. Tôi đã nhìn chằm chằm vào hex quá lâu và tôi nghĩ rằng mình đã kiếm được một kỳ nghỉ xứng đáng. Tất cả các bạn hãy cẩn thận và nếu bạn có bất kỳ câu hỏi nào, vui lòng viết chúng trong phần bình luận bên dưới. Tôi còn rất mới với cuộc phiêu lưu viết mã JPEG này nhưng tôi sẽ cố gắng trả lời nhiều nhất có thể 😄

Từ biệt. 👋 ❤️

đọc thêm

Nếu bạn muốn đi sâu vào chi tiết hơn, bạn có thể xem một số tài nguyên tôi đã sử dụng khi viết bài này. Tôi cũng đã thêm một số liên kết bổ sung cho một số nội dung thú vị liên quan đến JPEG

Làm cách nào để tạo hình ảnh trong Python?

Tạo hình ảnh nổi bật bằng Python [Gối] .
Cài đặt thư viện gối. Để thực hiện bài hướng dẫn lập trình ảnh Python này, chúng ta sẽ sử dụng Gối. .
Thêm các tính năng của hình ảnh của bạn. .
Tìm hình nền của bạn. .
Tạo các mẫu màu. .
Xác định chức năng. .
Chạy chức năng

Làm cách nào để chuyển đổi RGB sang JPG bằng Python?

Tôi có ý nghĩ về. .
Tạo một hình ảnh jpg mới bằng cách sử dụng. Rebuilded_image = Hình ảnh. mới['RGB', [x, y]]
Thay đổi giá trị pixel RGB của Rebuilded_image bằng giá trị của image_RGB

Python có thể tạo hình ảnh không?

Bài viết này là tổng quan ngắn gọn về ba cách để tạo hình ảnh bằng Python. Naive Bayes, GAN và VAE . Mỗi người sử dụng bộ dữ liệu chữ số viết tay MNIST. Hình ảnh có thể được tạo bằng Naive Bayes; .

Chủ Đề