การบีบอัดภาพ: JPEG และ JPEG2000 การประดิษฐ์ JPEG

อัลกอริธึมได้รับการพัฒนาโดย Joint Photographic Expert Group สำหรับการบีบอัดภาพ 24 บิตและระดับสีเทาโดยเฉพาะในปี 1991 อัลกอริธึมนี้บีบอัดรูปภาพสองระดับได้ไม่ดีนัก แต่สามารถจัดการรูปภาพที่มีโทนสีต่อเนื่องได้ดี ซึ่งพิกเซลใกล้เคียงมักจะมีสีใกล้เคียงกัน โดยปกติแล้วตาจะไม่สามารถสังเกตเห็นความแตกต่างใดๆ เมื่อบีบอัดด้วยวิธีนี้ 10 หรือ 20 เท่า

อัลกอริธึมจะขึ้นอยู่กับ DCT ที่ใช้กับเมทริกซ์ของบล็อกภาพที่แยกจากกันขนาด 8x8 พิกเซล DCT จะสลายบล็อกเหล่านี้ตามแอมพลิจูดของความถี่บางความถี่ ผลลัพธ์คือเมทริกซ์ซึ่งตามกฎแล้วค่าสัมประสิทธิ์จำนวนมากใกล้กับศูนย์ซึ่งสามารถแสดงในรูปแบบตัวเลขคร่าวๆ เช่น ในรูปแบบเชิงปริมาณโดยไม่สูญเสียคุณภาพการบูรณะอย่างมีนัยสำคัญ

พิจารณาการทำงานของอัลกอริธึมโดยละเอียด สมมติว่าภาพสี 24 บิตกำลังถูกบีบอัด ในกรณีนี้ เราได้รับขั้นตอนการทำงานดังต่อไปนี้

ขั้นตอนที่ 1แปลรูปภาพจาก พื้นที่ RGBลงในช่องว่าง YCbCr โดยใช้นิพจน์ต่อไปนี้:

ให้เราสังเกตทันทีว่าการแปลงผกผันนั้นได้มาอย่างง่ายดายโดยการคูณ เมทริกซ์ผกผันลงในเวกเตอร์ ซึ่งโดยพื้นฐานแล้วคือปริภูมิ YUV:

.

ขั้นตอนที่ 2เราแบ่งภาพต้นฉบับออกเป็นเมทริกซ์ขนาด 8x8 เราสร้างเมทริกซ์ DCT ที่ใช้งานได้สามตัวจากแต่ละอัน - 8 บิตแยกกันสำหรับแต่ละส่วนประกอบ ที่อัตราส่วนการบีบอัดสูง บล็อก 8x8 จะถูกแยกย่อยเป็นส่วนประกอบ YCbCr ในรูปแบบ 4:2:0 กล่าวคือ ส่วนประกอบสำหรับ Cb และ Cr ถูกนำผ่านจุดในแถวและคอลัมน์

ขั้นตอนที่ 3การใช้ DCT กับบล็อกรูปภาพ 8x8 พิกเซล อย่างเป็นทางการ DCT โดยตรงสำหรับบล็อก 8x8 สามารถเขียนเป็นได้

ที่ไหน - เนื่องจาก DCT เป็น "หัวใจ" ของอัลกอริธึม JPEG ในทางปฏิบัติจึงแนะนำให้คำนวณโดยเร็วที่สุด วิธีง่ายๆ ในการเร่งความเร็วการคำนวณคือการคำนวณฟังก์ชันโคไซน์ล่วงหน้าและจัดตารางผลลัพธ์ ยิ่งไปกว่านั้น เมื่อพิจารณาถึงมุมตั้งฉากของฟังก์ชันโคไซน์ด้วย ความถี่ที่แตกต่างกันสูตรข้างต้นสามารถเขียนได้เป็น

.

นี่คือเมทริกซ์ขององค์ประกอบ 8x8 ซึ่งอธิบายปริภูมิ 8 มิติ เพื่อแสดงคอลัมน์ของบล็อกในปริภูมินี้ เมทริกซ์เป็นเมทริกซ์แบบย้ายและทำสิ่งเดียวกัน แต่สำหรับแถวบล็อก ผลลัพธ์คือการแปลงแบบแยกส่วนได้ ซึ่งเขียนในรูปแบบเมทริกซ์เป็น

นี่คือผลลัพธ์ของ DCT ซึ่งการคำนวณต้องใช้การดำเนินการคูณและการบวกเกือบเท่าๆ กัน ซึ่งน้อยกว่าการคำนวณโดยตรงโดยใช้สูตรด้านบนอย่างมาก ตัวอย่างเช่น หากต้องการแปลงรูปภาพขนาด 512x512 พิกเซล คุณจะต้องใช้ การดำเนินการทางคณิตศาสตร์- เมื่อพิจารณาองค์ประกอบความสว่าง 3 องค์ประกอบ เราจะได้ค่าการดำเนินการทางคณิตศาสตร์ 12,582,912 รายการ จำนวนการคูณและการบวกสามารถลดลงได้อีกโดยใช้อัลกอริทึม การแปลงอย่างรวดเร็วฟูริเยร์ ด้วยเหตุนี้ ในการแปลงบล็อกขนาด 8x8 หนึ่งบล็อก คุณจะต้องทำการคูณ 54 ครั้ง การบวก 468 ครั้ง และการเลื่อนบิต

จากผลของ DCT เราได้เมทริกซ์ซึ่งมีสัมประสิทธิ์ทางด้านซ้าย มุมบนสอดคล้องกับองค์ประกอบความถี่ต่ำของภาพและที่มุมขวาล่าง - ความถี่สูง

ขั้นตอนที่ 4การหาปริมาณ ในขั้นตอนนี้ ข้อมูลบางอย่างจะถูกยกเลิก ที่นี่แต่ละตัวเลขจากเมทริกซ์จะถูกหารด้วย หมายเลขพิเศษจาก "ตารางปริมาณ" และผลลัพธ์จะถูกปัดเศษให้เป็นจำนวนเต็มที่ใกล้ที่สุด:

.

นอกจากนี้ สำหรับแต่ละเมทริกซ์ Y, Cb และ Cr คุณสามารถตั้งค่าตารางปริมาณของคุณเองได้ มาตรฐาน JPEG ยังอนุญาตให้ใช้ตารางปริมาณของตัวเองได้ซึ่งจะต้องถูกส่งไปยังตัวถอดรหัสพร้อมกับข้อมูลที่บีบอัดซึ่งจะเพิ่มขึ้น ขนาดโดยรวมไฟล์. เห็นได้ชัดว่าเป็นเรื่องยากสำหรับผู้ใช้ในการเลือกค่าสัมประสิทธิ์ 64 ค่าได้อย่างอิสระ ดังนั้นมาตรฐาน JPEG จึงใช้สองวิธีสำหรับเมทริกซ์การหาปริมาณ ประการแรกคือมาตรฐาน JPEG มีตารางปริมาณที่แนะนำสองตาราง ตารางหนึ่งสำหรับลูมาและอีกตารางหนึ่งสำหรับโครมิแนนซ์ ตารางเหล่านี้แสดงไว้ด้านล่าง วิธีที่สองคือการสังเคราะห์ (การคำนวณแบบทันที) ตารางปริมาณที่ขึ้นอยู่กับพารามิเตอร์หนึ่งตัวที่ผู้ใช้ระบุ ตัวตารางนั้นถูกสร้างขึ้นตามสูตร

ขั้นตอนการหาปริมาณคือจุดที่ควบคุมอัตราส่วนการบีบอัดและจุดที่สูญเสียมากที่สุด เป็นที่ชัดเจนว่าการระบุตารางปริมาณที่มีค่าสัมประสิทธิ์สูง เราจะได้ค่าศูนย์มากขึ้น ส่งผลให้อัตราส่วนการบีบอัดสูงขึ้น

ผลกระทบเฉพาะของอัลกอริทึมยังสัมพันธ์กับการหาปริมาณด้วย ที่ค่าขนาดใหญ่ของขั้นตอนการหาปริมาณ การสูญเสียอาจมากจนภาพแบ่งออกเป็นสี่เหลี่ยมสีเดียวขนาด 8x8 ในทางกลับกัน การสูญเสียในความถี่สูงสามารถแสดงออกมาในสิ่งที่เรียกว่า "เอฟเฟกต์กิ๊บส์" เมื่อมี "รัศมี" ที่มีลักษณะคล้ายคลื่นเกิดขึ้นรอบๆ รูปทรงที่มีการเปลี่ยนสีที่คมชัด

ขั้นตอนที่ 5เราแปลงเมทริกซ์ 8x8 ให้เป็นเวกเตอร์ 64 องค์ประกอบโดยใช้การสแกนซิกแซก (รูปที่ 2)

ข้าว. 2. การสแกนซิกแซก

เป็นผลให้ตามกฎแล้วค่าสัมประสิทธิ์ที่ไม่เป็นศูนย์จะถูกเขียนที่จุดเริ่มต้นของเวกเตอร์และสายโซ่ของศูนย์จะก่อตัวที่ส่วนท้าย

ขั้นตอนที่ 6เราแปลงเวกเตอร์โดยใช้อัลกอริธึม RLE ที่ปรับเปลี่ยนซึ่งเอาต์พุตเป็นคู่ของประเภท (ข้าม, ตัวเลข) โดยที่ "ข้าม" เป็นตัวนับของศูนย์ที่ข้ามและ "ตัวเลข" คือค่าที่ต้องใส่ในหน้าถัดไป เซลล์ ตัวอย่างเช่น เวกเตอร์ 1118 3 0 0 0 -2 0 0 0 0 1 ... จะถูกยุบเป็นคู่ (0, 1118) (0,3) (3,-2) (4,1) ... .

ควรสังเกตว่าหมายเลขแรกของส่วนประกอบที่แปลงแล้วนั้นโดยพื้นฐานแล้วเท่ากับความสว่างเฉลี่ยของบล็อก 8x8 และเรียกว่าค่าสัมประสิทธิ์ DC เหมือนกันสำหรับบล็อกรูปภาพทั้งหมด สถานการณ์นี้ชี้ให้เห็นว่าค่าสัมประสิทธิ์ DC สามารถบีบอัดได้อย่างมีประสิทธิภาพหากไม่ได้จดจำไว้ ค่าสัมบูรณ์และสัมพันธ์กันในรูปแบบของความแตกต่างระหว่างค่าสัมประสิทธิ์ DC ของบล็อกปัจจุบันและค่าสัมประสิทธิ์ DC ของบล็อกก่อนหน้า และจดจำค่าสัมประสิทธิ์แรกตามที่เป็นอยู่ ในกรณีนี้ การเรียงลำดับค่าสัมประสิทธิ์ DC สามารถทำได้เช่นนี้ (รูปที่ 3) ค่าสัมประสิทธิ์ที่เหลือซึ่งเรียกว่าค่าสัมประสิทธิ์ AC ยังคงไม่เปลี่ยนแปลง

ขั้นตอนที่ 7เรารวบรวมคู่ผลลัพธ์โดยใช้รหัส Huffman ที่ไม่สม่ำเสมอกับตารางคงที่ นอกจากนี้ สำหรับค่าสัมประสิทธิ์ DC และ AC รหัสที่แตกต่างกัน, เช่น. ตารางต่าง ๆ พร้อมรหัส Huffman

ข้าว. 3. รูปแบบการสั่งซื้อค่าสัมประสิทธิ์ DC

ข้าว. 4. บล็อกไดอะแกรมของอัลกอริทึม JPEG

กระบวนการกู้คืนรูปภาพในอัลกอริธึมนี้มีความสมมาตรอย่างสมบูรณ์ วิธีนี้ช่วยให้คุณบีบอัดภาพได้ 10-15 เท่าโดยไม่สูญเสียการมองเห็นอย่างเห็นได้ชัด

เมื่อพัฒนามาตรฐานนี้ เราได้รับคำแนะนำจากข้อเท็จจริงที่ว่า อัลกอริทึมนี้ต้องบีบอัดภาพค่อนข้างเร็ว - ไม่เกินหนึ่งนาทีสำหรับภาพโดยเฉลี่ย นี่คือในปี 1991! และการใช้งานฮาร์ดแวร์ควรจะค่อนข้างง่ายและราคาถูก ในกรณีนี้ อัลกอริธึมจะต้องมีความสมมาตรในเวลาทำงาน การดำเนินการ ข้อกำหนดล่าสุดทำ ลักษณะที่เป็นไปได้กล้องดิจิตอลที่ถ่ายภาพ 24 บิต หากอัลกอริธึมไม่สมมาตร คงไม่เป็นที่พอใจที่จะรอเป็นเวลานานเพื่อให้อุปกรณ์ "ชาร์จ" และบีบอัดภาพ

แม้ว่าอัลกอริทึม JPEG จะเป็นมาตรฐาน ISO แต่รูปแบบไฟล์ยังไม่ได้รับการแก้ไข การใช้ประโยชน์จากสิ่งนี้ ผู้ผลิตจะสร้างรูปแบบของตนเองที่เข้ากันไม่ได้ ดังนั้นจึงสามารถเปลี่ยนอัลกอริธึมได้ ดังนั้นตารางอัลกอริทึมภายในที่แนะนำโดย ISO จะถูกแทนที่ด้วยตารางของตัวเอง นอกจากนี้ยังมีตัวเลือก JPEG สำหรับแอปพลิเคชันเฉพาะอีกด้วย

“การนำอัลกอริธึมไปใช้

JPEG และ JPEG2000"

สมบูรณ์:

นักเรียนกลุ่ม 819

อูการอฟ มิทรี

หลักการทำงานของอัลกอริธึม JPEG และ JPEG2000

1. อัลกอริธึม JPEG

JPEG (Joint Photographic Experts Group) เป็นวิธีการบีบอัดภาพถ่ายที่ใช้กันอย่างแพร่หลาย รูปแบบไฟล์ที่มีข้อมูลที่ถูกบีบอัดมักเรียกว่า JPEG; นามสกุลที่พบบ่อยที่สุดสำหรับไฟล์ดังกล่าวคือ .jpeg, .jfif, .jpg, .JPG หรือ .JPE อย่างไรก็ตาม ในจำนวนนี้ .jpg ถือเป็นส่วนขยายที่ได้รับความนิยมสูงสุดในทุกแพลตฟอร์ม

อัลกอริธึม JPEG เป็นอัลกอริธึมการบีบอัด ด้วยการสูญเสียคุณภาพ.

ขอบเขตการใช้งาน

รูปแบบนี้คือรูปแบบการบีบอัดแบบสูญเสียข้อมูล ดังนั้นจึงไม่ถูกต้องที่จะคิดว่า JPEG เป็นการจัดเก็บข้อมูลเป็น 8 บิตต่อช่องสัญญาณ (24 บิตต่อพิกเซล) ในทางกลับกันเนื่องจากข้อมูลถูกบีบอัดด้วย รูปแบบ JPEGและข้อมูลที่คลายการบีบอัดมักจะแสดงเป็น 8 บิตต่อช่องสัญญาณ บางครั้งมีการใช้คำศัพท์นี้ นอกจากนี้ยังรองรับการบีบอัดภาพฮาล์ฟโทนขาวดำอีกด้วย

เมื่อบันทึกไฟล์ JPEG คุณสามารถระบุระดับคุณภาพได้ รวมถึงระดับการบีบอัด ซึ่งโดยปกติจะระบุไว้ในหน่วยทั่วไปบางหน่วย เช่น ตั้งแต่ 1 ถึง 100 หรือตั้งแต่ 1 ถึง 10 จำนวนที่มากขึ้นจะสอดคล้องกับคุณภาพที่ดีขึ้น แต่ขนาดไฟล์เพิ่มขึ้น โดยปกติแล้วความแตกต่างของคุณภาพระหว่าง 90 ถึง 100 นั้นแทบจะมองไม่เห็นด้วยตา ควรจำไว้ว่าอิมเมจที่ได้รับการกู้คืนทีละบิตจะแตกต่างจากรูปภาพต้นฉบับเสมอ ความเข้าใจผิดที่พบบ่อยก็คือ คุณภาพ JPEGเหมือนกับการแบ่งปันข้อมูลที่เก็บไว้

ขั้นตอนการเข้ารหัส

กระบวนการบีบอัด JPEG ประกอบด้วยหลายขั้นตอน:

1. แปลงรูปภาพให้เป็นพื้นที่สีที่เหมาะสมที่สุด

ในกรณีที่มีการใช้งาน พื้นที่สีความสว่าง/สี (YCbCr) ทำให้ได้อัตราส่วนการบีบอัดที่ดีที่สุด บน ในขั้นตอนนี้การเข้ารหัสโดยใช้อัตราส่วนสีที่เหมาะสม รุ่น RGBแปลงเป็น YCbCr:

Y = 0.299*ร + 0.587*G + 0.114*B

Cb = - 0.1687*R – 0.3313*G + 0.5*B

Cr = 0.5*R – 0.4187*G – 0.0813*B
ในระหว่างการถอดรหัส สามารถใช้การแปลงผกผันที่เหมาะสมได้:
R = Y + 1.402*Cr

G = Y – 0.34414*Cb – 0.71414*Cr

B = Y + 1.772*Cb
หมายเหตุเกี่ยวกับ Y,Cb,Cr ในระบบการมองเห็นของมนุษย์:

ดวงตา โดยเฉพาะเรตินา มีเซลล์สองประเภทเป็นตัววิเคราะห์การมองเห็น ได้แก่ เซลล์การมองเห็นตอนกลางคืนที่รับรู้เฉพาะเฉดสีเทา (จากสีขาวสว่างไปจนถึงสีดำเข้ม) และเซลล์การมองเห็นตอนกลางวันที่รับรู้สีอ่อน ๆ เซลล์แรกให้ สี RGBตรวจจับระดับความสว่างที่คล้ายกับค่า Y เซลล์อื่นๆ ที่รับผิดชอบในการรับรู้เฉดสี จะกำหนดค่าที่เกี่ยวข้องกับความแตกต่างของสี


2. การสุ่มตัวอย่างส่วนประกอบสีโดยการเฉลี่ยกลุ่มพิกเซล

ข้อมูลภาพส่วนใหญ่ที่ดวงตามนุษย์ไวต่อแสงมากที่สุดประกอบด้วยส่วนประกอบความสว่างระดับสีเทา (Y) ความถี่สูงของปริภูมิสี YCbCr องค์ประกอบสีอีกสององค์ประกอบ (Cb และ Cr) มีข้อมูลสีความถี่สูงซึ่งดวงตาของมนุษย์มีความไวน้อยกว่า ดังนั้นจึงสามารถละทิ้งบางส่วนออกไปได้ และด้วยเหตุนี้จึงสามารถลดจำนวนพิกเซลที่นำมาพิจารณาสำหรับช่องสีได้

1) พิมพ์ 4:2:0 (เมื่อรูปภาพแบ่งออกเป็นสี่เหลี่ยมจัตุรัสขนาด 2x2 พิกเซล และในแต่ละพิกเซลทั้งหมดจะได้รับ ค่าเดียวกันช่อง Cb และ Cr และความสว่าง Y ยังคงแตกต่างกันในแต่ละช่อง)

2) ประเภท 4:2:2 (การรวมกันตามส่วนประกอบของสีจะเกิดขึ้นในแนวนอนในกลุ่มพิกเซลสองพิกเซลเท่านั้น)

3) ประเภท 4:4:4 หมายความว่าแต่ละพิกเซลในแต่ละแถวมีค่าเฉพาะของส่วนประกอบ Y, Cb และ Cr (รูปที่ 1 ก)

4) พิมพ์ 4:2:2. โดยการสุ่มตัวอย่างสัญญาณโครมิแนนซ์ด้วยปัจจัย 2 ในแนวนอน เราได้มาจากสตรีม YCbCr 4: 4: 4 และสตรีม YCbCr 4: 2: 2 รายการ “4: 2: 2” หมายความว่าในบรรทัดเดียวมีค่าความสว่าง 4 ค่าสำหรับค่าสี 2 ค่า (ดูรูปที่ 1 b) สัญญาณ YCbCr 4:2:2 มีคุณภาพของภาพด้อยกว่าสัญญาณ YCbCr 4:4:4 เล็กน้อยมาก แต่แบนด์วิดท์ที่ต้องการจะลดลง 33% ของสัญญาณต้นฉบับ

3. การใช้การแปลงโคไซน์แบบไม่ต่อเนื่องเพื่อลดความซ้ำซ้อนของข้อมูลภาพ

ขั้นตอนหลักของอัลกอริทึมคือการแปลงโคไซน์แบบไม่ต่อเนื่อง (DCT หรือ DCT) ซึ่งเป็นการแปลงฟูริเยร์ประเภทหนึ่ง ใช้เมื่อทำงานกับรูปภาพเพื่อวัตถุประสงค์ต่างๆ ไม่ใช่แค่เพื่อการบีบอัดเท่านั้น การเปลี่ยนไปใช้การแสดงความถี่ของค่าพิกเซลทำให้เราสามารถดูภาพที่แตกต่าง ประมวลผล และบีบอัดสิ่งที่น่าสนใจสำหรับเรา ยิ่งไปกว่านั้น เมื่อทราบค่าสัมประสิทธิ์การแปลงแล้ว เราก็สามารถดำเนินการตรงกันข้ามได้เสมอ - คืนภาพต้นฉบับ

DCT นำไปใช้กับบล็อกโดยตรง (ในกรณีของเราคือ 8x8 พิกเซล) ของรูปภาพจะมีลักษณะดังนี้:

โดยที่ x, y คือพิกัดเชิงพื้นที่ของพิกเซล (0..7)

f(x,y) - ค่าพิกเซลของ macroblock ดั้งเดิม (เช่นความสว่าง)

u,v - พิกัดพิกเซลในการแทนความถี่ (0..7)

w(u) =1/SQRT(2) สำหรับ u=0 ในกรณีอื่นๆ w(u)=1 (SQRT - รากที่สอง)

w(v) =1/SQRT(2) สำหรับ v=0 ในกรณีอื่นๆ w(v)=1

หรือในรูปแบบเมทริกซ์:

4. การหาปริมาณของแต่ละบล็อกของค่าสัมประสิทธิ์ DCT โดยใช้ฟังก์ชันการถ่วงน้ำหนักที่ได้รับการปรับปรุงให้เหมาะสมโดยคำนึงถึงการรับรู้ทางสายตาของมนุษย์

การแปลงโคไซน์แบบไม่ต่อเนื่องจะเตรียมข้อมูลสำหรับการบีบอัดและการปัดเศษแบบสูญเสีย สำหรับแต่ละองค์ประกอบของเมทริกซ์ที่กำลังถูกแปลง จะมีองค์ประกอบเมทริกซ์ที่สอดคล้องกัน การหาปริมาณจะได้เมทริกซ์ผลลัพธ์โดยการหารแต่ละองค์ประกอบของเมทริกซ์ที่ถูกแปลงโดยองค์ประกอบที่สอดคล้องกันของเมทริกซ์เชิงปริมาณแล้วปัดเศษผลลัพธ์ให้เป็นจำนวนเต็มที่ใกล้ที่สุด เมื่อรวบรวมเมทริกซ์เชิงปริมาณ องค์ประกอบขนาดใหญ่จะอยู่ที่มุมซ้ายล่าง ดังนั้นเมื่อหารด้วยองค์ประกอบเหล่านั้น ข้อมูลในมุมนี้หลังจากการแปลงโคไซน์แบบไม่ต่อเนื่อง (โดยเฉพาะอย่างยิ่งส่วนที่การปัดเศษจะเจ็บปวดน้อยกว่า) จะถูกปัดเศษมากขึ้น ตามลำดับ ข้อมูลสูญหายสำคัญสำหรับเราน้อยกว่าสิ่งที่เหลืออยู่


5. ขั้นตอนการบีบอัดรอง

ขั้นตอนสุดท้ายของตัวเข้ารหัส JPEG คือการเข้ารหัสเมทริกซ์ผลลัพธ์

5.1 การเรียงสับเปลี่ยนซิกแซกของค่าสัมประสิทธิ์ DCT 64 ตัว

หลังจากที่เราทำการแปลง DCT กับบล็อกค่าขนาด 8x8 แล้ว เราก็ได้ บล็อกใหม่ 8x8. จากนั้น บล็อก 8x8 นี้จะถูกเคลื่อนที่ในรูปแบบซิกแซกดังนี้:

(ตัวเลขในบล็อก 8x8 ระบุลำดับที่เราสแกนเมทริกซ์ 8x8 แบบ 2 มิติ)

0, 1, 5, 6,14,15,27,28,

2, 4, 7,13,16,26,29,42,

3, 8,12,17,25,30,41,43,

9,11,18,24,31,40,44,53,

10,19,23,32,39,45,52,54,

20,22,33,38,46,51,55,60,

21,34,37,47,50,56,59,61,

35,36,48,49,57,58,62,63

อย่างที่คุณเห็น อย่างแรกคือมุมซ้ายบน (0,0) จากนั้นเป็นค่าที่ (0,1) จากนั้น (1,0) จากนั้น (2,0), (1,1), (0, 2), (0.3), (1.2), (2.1), (3.0) ฯลฯ

หลังจากที่เราซิกแซกเมทริกซ์ 8x8 แล้ว ตอนนี้เรามีเวกเตอร์ที่มีค่าสัมประสิทธิ์ 64 ตัว (0..63) ประเด็นของเวกเตอร์ซิกแซกนี้คือเรากำลังดูค่าสัมประสิทธิ์ 8x8 DCT เพื่อเพิ่มความถี่เชิงพื้นที่ ดังนั้นเราจึงได้เวกเตอร์ที่จัดเรียงตามเกณฑ์ความถี่เชิงพื้นที่: ค่าแรกของเวกเตอร์ (ดัชนี 0) สอดคล้องกับความถี่ต่ำสุดในภาพ - ซึ่งแสดงด้วยคำว่า DC เมื่อดัชนีบนเวกเตอร์เพิ่มขึ้น เราจะได้ค่าที่สอดคล้องกับความถี่ที่สูงขึ้น (ค่าที่มีดัชนี 63 สอดคล้องกับความกว้างของ ความถี่สูงในบล็อก 8x8) ค่าสัมประสิทธิ์ DCT ที่เหลือจะแสดงด้วย AC

5.2 RunLength การเข้ารหัสเป็นศูนย์ (RLE)

ตอนนี้เรามีเวกเตอร์ที่มีลำดับเลขศูนย์ยาวๆ เราสามารถใช้สิ่งนี้โดยการเข้ารหัสเลขศูนย์ที่อยู่ติดกัน สำคัญ: คุณจะเห็นสาเหตุในภายหลัง แต่ที่นี่ เรากำลังข้ามการเข้ารหัสของสัมประสิทธิ์เวกเตอร์แรก (สัมประสิทธิ์ DC) ซึ่งมีการเข้ารหัสต่างกัน พิจารณาเวกเตอร์ 64 ดั้งเดิมเป็นเวกเตอร์ 63 (นี่คือเวกเตอร์ 64 ที่ไม่มีสัมประสิทธิ์แรก)

สมมุติว่าเรามี 57,45,0,0,0,0,23,0,-30,-16,0,0,1,0,0,0,0,0,0, เพียง 0,... .0

ที่นี่ - เป็น RLC การบีบอัด JPEGทำเพื่อตัวอย่างนี้:

(0.57); (0.45); (4.23); (1,-30); (0,-16); (2.1); อีโอบี

อย่างที่คุณเห็น เราเข้ารหัสสำหรับแต่ละค่าที่ไม่ใช่ 0 ด้วยจำนวนศูนย์นำหน้าที่อยู่ติดกันก่อนค่า จากนั้นเราจะบวกค่านั้น หมายเหตุอีกประการหนึ่ง: EOB เป็นรูปแบบสั้นสำหรับ End of Block ซึ่งเป็นค่าเข้ารหัสพิเศษ (เครื่องหมาย) หากเราไปถึงตำแหน่งบนเวกเตอร์ซึ่งเรามีเพียงเวกเตอร์ศูนย์จนถึงจุดสิ้นสุด เราจะจัดสรรตำแหน่งนั้นด้วย EOB และการบีบอัด RLC ที่สมบูรณ์ของเวกเตอร์เชิงปริมาณ

[โปรดทราบว่าหากเวกเตอร์เชิงปริมาณไม่ได้สิ้นสุดด้วยศูนย์ (มีองค์ประกอบสุดท้ายไม่ใช่ 0) เราจะไม่มีโทเค็น EOB]

(0,57); (0,45); (4,23); (1,-30); (0,-16); (2,1); (0,0)

สิ่งสำคัญอีกอย่างหนึ่ง: สมมติว่ามีที่ไหนสักแห่งบนเวกเตอร์เชิงปริมาณที่เรามี:

57, สิบแปดศูนย์, 3, 0.0 ,0.0 2, สามสิบสามศูนย์, 895, EOB

การเข้ารหัส JPG Huffman กำหนดข้อจำกัดว่าจำนวนศูนย์นำหน้าจะต้องเข้ารหัส เนื่องจากค่า 4 บิตต้องไม่เกิน 15

ดังนั้น ตัวอย่างก่อนหน้านี้ควรเขียนโค้ดเป็น:

(0,57); (15,0) (2,3); (4,2); (15,0) (15,0) (1,895), (0,0)

(15,0) เป็นค่าเข้ารหัสพิเศษที่ระบุว่ามีเลขศูนย์ต่อเนื่องกัน 16 ตัว

5.3 ขั้นตอนสุดท้าย - การเข้ารหัส Huffman

ก่อนอื่น หมายเหตุสำคัญ: แทนที่จะจัดเก็บค่าจริง มาตรฐาน JPEG จะกำหนดสิ่งที่เราจัดเก็บ ขนาดขั้นต่ำเป็นบิตที่เราสามารถเก็บค่านี้ไว้ได้ (ซึ่งเรียกว่าหมวดหมู่ของค่านี้) จากนั้นจึงแสดงค่านี้โดยใช้รหัสบิตดังนี้

7,..,-4,4,..,7 3 000,001,010,011,100,101,110,111

15,..,-8,8,..,15 4 0000,..,0111,1000,..,1111

31,..,-16,16,..,31 5 00000,..,01111,10000,..,11111

63,..,-32,32,..,63 6 .

127,..,-64,64,..,127 7 .

255,..,-128,128,..,255 8 .

511,..,-256,256,..,511 9 .

1023,..,-512,512,..,1023 10 .

2047,..,-1024,1024,..,2047 11 .

4095,..,-2048,2048,..,4095 12 .

8191,..,-4096,4096,..,8191 13 .

16383,..,-8192,8192,..,16383 14 .

32767,..,-16384,16384,..,32767 15 .

ต่อไปสำหรับตัวอย่างก่อนหน้านี้:

(0,57); (0,45); (4,23); (1,-30); (0,-8); (2,1); (0,0)

มาเข้ารหัสเฉพาะค่าทางขวามือของคู่นี้ ยกเว้นคู่ที่เป็นโทเค็นพิเศษ เช่น (0,0) หรือ (ถ้าเราต้องมี) (15,0)

45 ในทำนองเดียวกันจะถูกเข้ารหัสเป็น (6.101101)

30 -> (5,00001)

และตอนนี้ เราจะเขียนสตริงของคู่อีกครั้ง:

(0,6), 111001; (0,6), 101101; (4,5), 10111; (1,5), 00001; (0,4), 0111; (2,1), 1; (0,0)

คู่ค่า 2 ค่าที่อยู่ในวงเล็บสามารถแสดงเป็นไบต์ได้ เนื่องจากในความเป็นจริง แต่ละค่าจาก 2 ค่าสามารถแสดงเป็นชิ้นขนาด 4 บิตได้ (จำนวนศูนย์นำหน้าจะน้อยกว่า 15 เสมอและมีค่าเท่ากับ หมวดหมู่ [ตัวเลขที่เข้ารหัสใน ไฟล์ JPG- ในพื้นที่ -32767..32767]) ในไบต์นี้ บิตสูงแสดงถึงจำนวนศูนย์ที่อยู่ข้างหน้า และบิตต่ำแสดงถึงหมวดหมู่ของค่าใหม่ที่ไม่ใช่ 0

ขั้นตอนการเข้ารหัสขั้นสุดท้ายคือให้ Huffman เข้ารหัสไบต์นี้ จากนั้นบันทึกเป็นไฟล์ JPG ในรูปแบบบิตสตรีม ซึ่งเป็นโค้ด Huffman ของไบต์นี้ ตามด้วยการแสดงค่าระดับบิตของตัวเลขนี้

ตัวอย่างเช่น สำหรับไบต์ 6 (เทียบเท่ากับ (0,6)) เรามีรหัส Huffman = 111000

21 = (1,5) - 11111110110

4 = (0,4) - 1011

33 = (2,1) - 11011

0 = EOB= (0,0) - 1,010

บิตสตรีมสุดท้ายที่เขียนในไฟล์ JPG ไปยังดิสก์สำหรับตัวอย่างก่อนหน้าคือ 63 สัมประสิทธิ์ (จำไว้ว่าเราข้ามค่าสัมประสิทธิ์แรก) -

111000 111001 111000 101101 1111111110011001 10111 11111110110 00001

1011 0111 11011 1 1010
ข้อดีและข้อเสีย

ข้อเสียของรูปแบบรวมถึงความจริงที่ว่าในการบีบอัดระดับสูงโครงสร้างข้อมูลบล็อกทำให้รู้สึกว่ารูปภาพจะ "แบ่งออกเป็นสี่เหลี่ยมจัตุรัส" (แต่ละขนาด 8x8 พิกเซล) ผลกระทบนี้สังเกตได้ชัดเจนเป็นพิเศษในพื้นที่ที่มีความถี่เชิงพื้นที่ต่ำ ( การเปลี่ยนแปลงที่ราบรื่นรูปภาพเช่น ท้องฟ้าแจ่มใส- ในพื้นที่ที่มีความถี่เชิงพื้นที่สูง (เช่น ขอบที่ตัดกันของภาพ) ลักษณะ "สิ่งแปลกปลอม" จะปรากฏขึ้น - โครงสร้างพิกเซลที่ผิดปกติซึ่งมีสีและ/หรือความสว่างบิดเบี้ยว นอกจากนี้รายละเอียดสีเล็กๆ น้อยๆ จะหายไปจากภาพ เราก็ไม่ควรลืมสิ่งนั้นเช่นกัน รูปแบบนี้ไม่สนับสนุนความโปร่งใส

อย่างไรก็ตาม แม้จะมีข้อบกพร่อง แต่ JPEG ก็แพร่หลายอย่างมากเนื่องจากมีอัตราส่วนการบีบอัดสูงเมื่อเทียบกับทางเลือกอื่นที่มีอยู่ในขณะที่เปิดตัว

2. อัลกอริธึม JPEG2000

อัลกอริธึม JPEG-2000 ได้รับการพัฒนาโดยผู้เชี่ยวชาญด้านการถ่ายภาพกลุ่มเดียวกับที่พัฒนา JPEG การก่อตัวของ JPEG เป็น มาตรฐานสากลแล้วเสร็จในปี 1992 ในปีพ.ศ. 2540 เห็นได้ชัดว่าจำเป็นต้องมีมาตรฐานใหม่ที่ยืดหยุ่นและมีประสิทธิภาพมากขึ้น ซึ่งได้รับการสรุปผลภายในฤดูหนาวปี พ.ศ. 2543

ความแตกต่างที่สำคัญระหว่างอัลกอริทึมใน JPEG 2000 และอัลกอริทึมใน JPEG มีดังนี้:

1) คุณภาพของภาพดีขึ้นด้วยการบีบอัดระดับสูง หรือสิ่งเดียวกันคืออัตราส่วนการอัดที่สูงกว่าแต่คุณภาพเท่ากันสำหรับอัตราส่วนการอัดที่สูง ผลที่ได้คือการลดขนาดกราฟิก "คุณภาพเว็บ" ที่ไซต์ส่วนใหญ่ใช้ลงอย่างเห็นได้ชัด

2) รองรับการเข้ารหัสแต่ละพื้นที่ด้วย คุณภาพดีที่สุด- เป็นที่ทราบกันว่าพื้นที่บางส่วนของภาพมีความสำคัญต่อการรับรู้ของมนุษย์ (เช่น ดวงตาในภาพถ่าย) ในขณะที่คุณภาพของพื้นที่อื่นๆ สามารถลดลงได้ (เช่น พื้นหลัง) ด้วยการเพิ่มประสิทธิภาพ "แบบแมนนวล" อัตราการบีบอัดจะเพิ่มขึ้นจนกว่าคุณภาพของส่วนสำคัญของภาพจะสูญเสียไป ตอนนี้เป็นไปได้ที่จะตั้งค่าคุณภาพในพื้นที่วิกฤติ โดยบีบอัดพื้นที่อื่นๆ ให้แรงยิ่งขึ้น เช่น เราได้รับอัตราการบีบอัดขั้นสุดท้ายที่ดียิ่งขึ้นด้วยคุณภาพของภาพที่เท่าเทียมกัน

3) อัลกอริธึมการบีบอัดหลักถูกแทนที่ด้วยเวฟเล็ต นอกเหนือจากการเพิ่มอัตราส่วนการบีบอัดที่ระบุแล้ว ยังทำให้สามารถกำจัดการบล็อก 8 พิกเซลที่เกิดขึ้นเมื่ออัตราส่วนการบีบอัดเพิ่มขึ้นได้ นอกจากนี้ ในตอนแรกการพัฒนาภาพที่ราบรื่นได้รวมอยู่ในมาตรฐานแล้ว (Progressive JPEG ซึ่งใช้งานบนอินเทอร์เน็ตอย่างแข็งขันปรากฏช้ากว่า JPEG มาก)

4) เพื่อเพิ่มอัตราส่วนการบีบอัด อัลกอริธึมจะใช้การบีบอัดทางคณิตศาสตร์ เดิมมาตรฐาน JPEG ยังรวมการบีบอัดทางคณิตศาสตร์ด้วย แต่ต่อมาถูกแทนที่ด้วยการบีบอัด Huffman ที่มีประสิทธิภาพน้อยกว่า เนื่องจากการบีบอัดทางคณิตศาสตร์ได้รับการคุ้มครองโดยสิทธิบัตร ขณะนี้สิทธิบัตรหลักหมดอายุแล้ว และมีโอกาสที่จะปรับปรุงอัลกอริทึมได้

5) รองรับการบีบอัดแบบไม่สูญเสียข้อมูล นอกเหนือจากการบีบอัดแบบ lossy ตามปกติแล้ว JPEG ใหม่ยังรองรับการบีบอัดแบบ lossless อีกด้วย มันจึงกลายเป็น การใช้งานที่เป็นไปได้ JPEG สำหรับบีบอัดภาพทางการแพทย์ ในการพิมพ์ โดยบันทึกข้อความไว้ข้างใต้ การรับรู้โอซีอาร์ระบบ ฯลฯ

6) รองรับการบีบอัดภาพบิตเดียว (2 สี) สำหรับการบันทึกรูปภาพบิตเดียว (ภาพวาดด้วยหมึก ข้อความที่สแกน ฯลฯ) ก่อนหน้านี้แนะนำให้ใช้ในระดับสากล รูปแบบ GIFเนื่องจากการบีบอัดโดยใช้ DCT ไม่ได้ผลอย่างมากสำหรับภาพที่มีการเปลี่ยนสีที่คมชัด ใน JPEG เมื่อบีบอัด รูปภาพ 1 บิตจะถูกแปลงเป็น 8 บิต เช่น เพิ่มขึ้น 8 เท่า หลังจากนั้นมีการพยายามบีบอัด มักจะน้อยกว่า 8 เท่า ตอนนี้เราสามารถแนะนำ JPEG 2000 เป็นอัลกอริธึมสากลได้แล้ว

7) รองรับความโปร่งใสในระดับรูปแบบ ขณะนี้ สามารถใช้พื้นหลังได้อย่างราบรื่นเมื่อสร้างหน้า WWW ไม่เพียงแต่ใน GIF แต่ยังใน JPEG 2000 นอกจากนี้ ยังรองรับความโปร่งใสไม่เพียงแค่ 1 บิตเท่านั้น (พิกเซลโปร่งใส/ทึบแสง) แต่ยังรองรับช่องสัญญาณแยกต่างหาก ซึ่ง จะอนุญาตให้คุณตั้งค่า การเปลี่ยนแปลงที่ราบรื่นจากภาพทึบเป็นพื้นหลังโปร่งใส

นอกจากนี้ ในระดับรูปแบบ รองรับการรวมข้อมูลลิขสิทธิ์ในภาพ รองรับการต้านทานข้อผิดพลาดบิตระหว่างการส่งและการออกอากาศ คุณสามารถขอเครื่องมือภายนอก (ปลั๊กอิน) สำหรับการขยายขนาดหรือการประมวลผล คุณสามารถรวมคำอธิบายได้ , ข้อมูลการค้นหา ฯลฯ .d.

ขั้นตอนการเข้ารหัส

กระบวนการบีบอัด JPEG2000 ประกอบด้วยหลายขั้นตอน:

1. แปลงภาพให้เป็นปริภูมิสีที่เหมาะสมที่สุด
ในขั้นตอนนี้ของการเขียนโค้ดโดยใช้ความสัมพันธ์ที่เหมาะสม รุ่นสี RGB แปลงเป็น YUV:

เมื่อคลายการบีบอัด จะใช้การแปลงผกผันที่สอดคล้องกัน:

2. เวฟเล็ตแบบแยกส่วนการเปลี่ยนแปลง

การแปลงเวฟเล็ตแบบแยก (DWT) ยังสามารถมีได้สองประเภท - สำหรับกรณีของการบีบอัดที่สูญเสีย และสำหรับการบีบอัดแบบไม่สูญเสีย

การเปลี่ยนแปลงในกรณีมิติเดียวนี้เป็นผลคูณสเกลาร์ของสัมประสิทธิ์ที่สอดคล้องกันและสตริงของค่า แต่เพราะว่า ค่าสัมประสิทธิ์จำนวนมากเป็นศูนย์ จากนั้นการแปลงเวฟเล็ตแบบตรงและแบบผกผันสามารถเขียนได้ด้วยสูตรต่อไปนี้ (เพื่อแปลงองค์ประกอบสุดขีดของเส้น จะใช้การขยาย 2 พิกเซลในแต่ละทิศทาง ซึ่งค่าจะสมมาตรกับ ค่าขององค์ประกอบของเส้นที่สัมพันธ์กับพิกเซลสุดขีด):
y(2*n + 1) = x(2*n + 1) - (int)(x(2*n) + x(2*n + 2)) / 2

y(2*n) = x(2*n) + (int)(y(2*n - 1) + y(2*n + 1) + 2) / 4

และในทางกลับกัน

x(2*n) = y(2*n) - (int)(y(2*n - 1) + y(2*n + 1) + 2) / 4

x(2*n + 1) = y(2*n + 1) + (int)(x(2*n) + x(2*n + 2)) / 2

3. การหาปริมาณของสัมประสิทธิ์

เช่นเดียวกับอัลกอริธึม JPEG การหาปริมาณจะใช้เมื่อเข้ารหัสรูปภาพเป็นรูปแบบ JPEG2000 การแปลงเวฟเล็ตแบบไม่ต่อเนื่องจะจัดเรียงค่าสัมประสิทธิ์ตามความถี่เช่นเดียวกับอะนาล็อก แต่ในรูปแบบใหม่นั้นต่างจาก JPEG ตรงที่มีเมทริกซ์เชิงปริมาณหนึ่งเมทริกซ์สำหรับรูปภาพทั้งหมด


4. ขั้นตอนการบีบอัดรอง

. เช่นเดียวกับ JPEG ขั้นตอนสุดท้ายในอัลกอริธึมการบีบอัดในรูปแบบใหม่คือการเข้ารหัสแบบไม่สูญเสียข้อมูล แต่ไม่เหมือนกับรูปแบบก่อนหน้านี้ JPEG2000 ใช้อัลกอริธึมการบีบอัดทางคณิตศาสตร์

การใช้งานซอฟต์แวร์

ในงานนี้มีการใช้อัลกอริธึม JPEG และ JPEG2000 อัลกอริธึมทั้งสองใช้การเข้ารหัสไปข้างหน้าและย้อนกลับ (ไม่มี ขั้นตอนสุดท้ายการบีบอัดรอง) การคำนวณ JPEG ใช้เวลานาน (ประมาณ 30 วินาที) เนื่องจากการคำนวณ DCT "โดยตรง" หากคุณต้องการเพิ่มความเร็วในการทำงานคุณควรคำนวณเมทริกซ์ DCT ในตอนแรก (ควรทำการเปลี่ยนแปลงในคลาส DCT)

ไปที่โปรแกรมกันดีกว่า:


  1. หลังจากเปิดตัวจะมีหน้าต่างปรากฏขึ้นที่ตำแหน่งนั้น

และคุณสามารถบันทึกได้โดยคลิกปุ่ม (2) และป้อนชื่อที่ต้องการในกล่องโต้ตอบ

  • ด้วยปัจจัยด้านคุณภาพที่มีขนาดใหญ่เพียงพอ รูปภาพจะเปลี่ยนไปอย่างมาก หากเป็นอัลกอริธึม JPEG บล็อกขนาด 8x8 จะมองเห็นได้ชัดเจน (ในกรณีของอัลกอริธึม JPEG2000 จะไม่มีการแบ่งบล็อก)
  • ถึง:

    หลังจาก:



    หลังจากคำนวณค่าสัมประสิทธิ์ DCT ทั้งหมดแล้ว จะต้องหาปริมาณ ในขั้นตอนนี้ ข้อมูลบางส่วนจะถูกละทิ้ง (การสูญเสียเล็กน้อยเกิดขึ้นในขั้นตอนก่อนหน้าเนื่องจากความแม่นยำอันจำกัดของการคำนวณบนคอมพิวเตอร์) แต่ละตัวเลขจากเมทริกซ์สัมประสิทธิ์ DCT จะถูกหารด้วยตัวเลขพิเศษจาก "ตารางปริมาณ" และผลลัพธ์จะถูกปัดเศษให้เป็นจำนวนเต็มที่ใกล้ที่สุด ตามที่ระบุไว้แล้ว จำเป็นต้องมีตารางดังกล่าวสามตารางสำหรับส่วนประกอบสีแต่ละสี มาตรฐาน JPEG อนุญาตให้มีสี่ตาราง และผู้ใช้สามารถเลือกตารางใดก็ได้เหล่านี้เพื่อกำหนดปริมาณส่วนประกอบสี ตัวเลขทั้งหมด 64 ตัวจากตารางปริมาณเป็นพารามิเตอร์ JPEG โดยหลักการแล้ว ผู้ใช้สามารถเปลี่ยนอัตราส่วนใดก็ได้เพื่อให้ได้อัตราส่วนการอัดที่สูงขึ้น ในทางปฏิบัติ การทดลองเช่นนี้เป็นเรื่องยากมาก จำนวนมากพารามิเตอร์ ดังนั้นซอฟต์แวร์ JPEG จึงใช้สองวิธี:

    1. ตารางปริมาณเริ่มต้น ตารางดังกล่าวสองตาราง ตารางหนึ่งสำหรับองค์ประกอบความส่องสว่าง (และการไล่สี สีเทา) และส่วนประกอบอื่นๆ ที่เป็นสีเป็นผลจากการวิจัยระยะยาวโดยมีการทดลองมากมายที่ดำเนินการโดยคณะกรรมการ JPEG เป็นส่วนหนึ่งของมาตรฐาน JPEG และทำซ้ำในตาราง 3.50. คุณสามารถดูได้ว่าค่าสัมประสิทธิ์ QC ของตารางเพิ่มขึ้นอย่างไรเมื่อย้ายจากมุมซ้ายบนไปยังมุมขวาล่าง สิ่งนี้สะท้อนให้เห็นถึงการลดลงของค่าสัมประสิทธิ์ DCT ที่สอดคล้องกับความถี่เชิงพื้นที่สูง

    2. คำนวณแล้ว ตารางที่เรียบง่ายค่าสัมประสิทธิ์การหาปริมาณ ขึ้นอยู่กับพารามิเตอร์ที่ผู้ใช้ระบุ สำนวนง่ายๆ เช่น รับประกันว่าค่าสัมประสิทธิ์ลดลงจากซ้ายบนไปขวาล่าง

    ความส่องสว่าง

    หากการหาปริมาณทำอย่างถูกต้อง จากนั้นในบล็อกของสัมประสิทธิ์ DCT จะมีค่าสัมประสิทธิ์ที่ไม่เป็นศูนย์เพียงไม่กี่ค่าเท่านั้น ซึ่งจะกระจุกตัวอยู่ที่มุมซ้ายบนของเมทริกซ์ ตัวเลขเหล่านี้เป็นผลลัพธ์ของอัลกอริธึม JPEG แต่จะต้องได้รับการบีบอัดเพิ่มเติมก่อนที่จะเขียนลงในไฟล์เอาต์พุต ในเอกสาร JPEG การบีบอัดนี้เรียกว่า "การเข้ารหัสเอนโทรปี" ซึ่งจะกล่าวถึงรายละเอียดใน § 3.7.5 มีการใช้เทคนิคสามประการในการเข้ารหัสเอนโทรปีเพื่อบีบอัดเมทริกซ์จำนวนเต็ม 8x8

    3. ตัวเลข 64 ตัวเรียงกันราวกับสแกนซิกแซก (ดูรูปที่ 3.5a) มีตัวเลขที่ไม่ใช่ศูนย์ที่จุดเริ่มต้น โดยปกติแล้วตามด้วยหางยาวของศูนย์ทั้งหมด เฉพาะตัวเลขที่ไม่ใช่ศูนย์ (หลังจากการเข้ารหัสที่เหมาะสม) เท่านั้นที่จะส่งออกไปยังไฟล์ ตามด้วย รหัสพิเศษ EOB (สิ้นสุดบล็อก, สิ้นสุดบล็อก) ไม่จำเป็นต้องบันทึกส่วนท้ายของศูนย์ทั้งหมด (คุณอาจพูดได้ว่า EOB เข้ารหัสชุดศูนย์ขนาดยาว)

    ตัวอย่าง: ในตาราง รูปที่ 3.51 แสดงรายการค่าสัมประสิทธิ์ DCT เชิงสมมุติ ซึ่งมีเพียง 4 ค่าเท่านั้นที่ไม่เป็นศูนย์ เมื่อซิกแซกเรียงลำดับตัวเลขเหล่านี้ จะได้ลำดับของสัมประสิทธิ์:

    โต๊ะ 3.51. สัมประสิทธิ์เชิงปริมาณ

    จะเขียนรูทีนย่อยสำหรับอ่านองค์ประกอบเมทริกซ์ในรูปแบบซิกแซกได้อย่างไร วิธีที่ง่ายที่สุดประกอบด้วยการติดตามเส้นทางนี้ด้วยตนเองและบันทึกผลลัพธ์ในอาร์เรย์ของโครงสร้าง zz ซึ่งแต่ละโครงสร้างประกอบด้วยคู่ของพิกัดเซลล์ที่เส้นทางซิกแซกผ่านไป (ดูรูปที่ 3.52)

    หากส่วนประกอบของโครงสร้าง zz ถูกกำหนดให้เป็น zz.r และ zz.с ดังนั้นเส้นทางซิกแซกจะเสร็จสมบูรณ์ได้โดยใช้วงจรต่อไปนี้

    4. ค่าสัมประสิทธิ์การแปลงที่ไม่เป็นศูนย์จะถูกบีบอัดโดยใช้วิธี Huffman (ดู§ 3.7.5)

    5. ตัวเลขตัวแรกของตัวเลขเหล่านี้ (ค่าสัมประสิทธิ์ DC ดูหน้า 145) จะถูกประมวลผลแยกจากตัวเลขอื่นๆ (ค่าสัมประสิทธิ์ AC)

    ข้าว. 3.52. พิกัดเส้นทางซิกแซก

    • บทช่วยสอน

    รปภ. ฉันถูกบังคับให้ลบการจัดรูปแบบ monospace วันหนึ่ง habraparser หยุดยอมรับการจัดรูปแบบภายในแท็กก่อนและโค้ด ข้อความทั้งหมดกลายเป็นข้าวต้ม ฝ่ายบริหารของ Habr ไม่สามารถช่วยฉันได้ ตอนนี้มันไม่สม่ำเสมอ แต่อย่างน้อยก็สามารถอ่านได้

    คุณเคยต้องการที่จะรู้ว่าไฟล์ jpg ทำงานอย่างไร? มาคิดกันตอนนี้! อุ่นเครื่องคอมไพเลอร์และโปรแกรมแก้ไข hex ที่คุณชื่นชอบ เราจะถอดรหัสสิ่งนี้:

    ฉันจงใจวาดภาพเล็กๆ นี่เป็น favicon ของ Google ที่คุ้นเคยแต่ถูกบีบอัดอย่างหนัก:

    ฉันเตือนคุณทันทีว่าคำอธิบายนั้นง่ายขึ้นและข้อมูลที่ให้มานั้นไม่สมบูรณ์ แต่จะเข้าใจข้อกำหนดได้ง่ายในภายหลัง

    แม้จะไม่รู้ว่าการเข้ารหัสเกิดขึ้นได้อย่างไร เราก็สามารถแยกบางสิ่งออกจากไฟล์ได้แล้ว
    - เครื่องหมายเริ่มต้น อยู่ที่จุดเริ่มต้นของไฟล์ jpg ทั้งหมดเสมอ
    ถัดมาเป็นไบต์ - นี่คือเครื่องหมายที่ระบุจุดเริ่มต้นของส่วนความคิดเห็น 2 ไบต์ถัดไป - ความยาวส่วน (รวม 2 ไบต์นี้ด้วย) ดังนั้นในอีกสองทางข้างหน้า - ความคิดเห็นนั้นเอง เหล่านี้คือรหัสอักขระ /// และ ")" เช่น ใบหน้าที่ยิ้มเป็นประจำ คุณสามารถดูได้ในบรรทัดแรกทางด้านขวาของโปรแกรมแก้ไขฐานสิบหก

    ทฤษฎีเล็กน้อย

    ทีละขั้นตอนสั้น ๆ :
    ลองคิดถึงลำดับที่สามารถเข้ารหัสข้อมูลนี้ได้ สมมติว่า อันดับแรก ช่อง Y ได้รับการเข้ารหัสอย่างสมบูรณ์สำหรับภาพทั้งหมด จากนั้น Cb และ Cr ทุกคนจำการโหลดรูปภาพบนไดอัลอัพได้ หากเข้ารหัสด้วยวิธีนี้ เราจะต้องรอให้โหลดรูปภาพทั้งหมดก่อนจึงจะปรากฏบนหน้าจอ จะไม่เป็นที่พอใจหากส่วนท้ายของไฟล์สูญหาย อาจมีเหตุผลที่ดีอื่น ๆ ดังนั้นข้อมูลที่เข้ารหัสจึงถูกจัดเรียงทีละรายการโดยเป็นส่วนเล็กๆ

    ฉันขอเตือนคุณว่าแต่ละบล็อก Y ij , Cb ij , Cr ij เป็นเมทริกซ์ของสัมประสิทธิ์ DCT ที่เข้ารหัสด้วยรหัส Huffman ในไฟล์จะจัดเรียงตามลำดับนี้: Y 00 Y 10 Y 01 Y 11 Cb 00 Cr 00 Y 20

    กำลังอ่านไฟล์

    เมื่อเราแยกความคิดเห็นออกมาแล้ว จะเข้าใจได้ง่ายว่า:
    • ไฟล์จะถูกแบ่งออกเป็นส่วนที่นำหน้าด้วยเครื่องหมาย
    • เครื่องหมายมีความยาว 2 ไบต์ โดยไบต์แรกเป็น
    • เกือบทุกเซกเตอร์จะเก็บความยาวไว้ 2 ไบต์ถัดไปหลังเครื่องหมาย
    เพื่อความสะดวก เรามาเน้นเครื่องหมาย:
    FF D8 FF FE 00 04 3A 29 FF DB 00 43 00 A0 6E 78



    FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 00
    43 01 AA B4 B4 F0 D2 F0 FF FF FF FF FF FF FF FF
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
    FF FF FF C0 00 11 08 00 10 00 10 03 01 22 00 02
    11 01 03 11 01 เอฟเอฟ C4 00 15 00 01 01 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 03 02 FF C4 00 1A
    10 01 00 02 03 01 00 00 00 00 00 00 00 00 00 00
    00 01 00 12 02 11 31 21 เอฟเอฟ C4 00 15 01 01 01 00
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 เอฟเอฟ
    C4 00 16 11 01 01 01 00 00 00 00 00 00 00 00 00
    00 00 00 00 11 00 01 FF DA 00 0C 03 01 00 02 11
    03 11 00 3F 00 TH E7 61 F2 1B D5 22 85 5D 04 3C
    82 C8 48 B1 ดีซี BF FF D9

    เครื่องหมาย: DQT - ตารางปริมาณ

    เอฟเอฟดีบี 00 43 00 A0 6E 78
    8C 78 64 A0 8C 82 8C B4 AA A0 BE F0 FF FF F0 กระแสตรง
    กระแสตรง F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
    FF FF FF FF FF FF FF FF FF FF FF FF FF

    ส่วนหัวของส่วนจะใช้เวลา 3 ไบต์เสมอ ในกรณีของเราก็คือ ส่วนหัวประกอบด้วย:
    ความยาว: 0x43 = 67 ไบต์
    ความยาวของค่าในตาราง: 0 (0 - 1 ไบต์, 1 - 2 ไบต์)
    [_0] รหัสตาราง: 0
    64 ไบต์ที่เหลือต้องเติมตาราง 8x8



    ดูลำดับของการกรอกค่าตารางให้ละเอียดยิ่งขึ้น คำสั่งนี้เรียกว่าคำสั่งซิกแซก:

    เครื่องหมาย: SOF0 - พื้นฐาน DCT

    เครื่องหมายนี้เรียกว่า SOF0 และหมายความว่ารูปภาพถูกเข้ารหัสโดยใช้วิธีการพื้นฐาน มันเป็นเรื่องธรรมดามาก แต่วิธีที่ได้รับความนิยมไม่น้อยบนอินเทอร์เน็ตคือวิธีการโปรเกรสซีฟที่คุ้นเคยเมื่อโหลดรูปภาพความละเอียดต่ำครั้งแรกจากนั้นจึงโหลดรูปภาพปกติ สิ่งนี้ช่วยให้คุณเข้าใจสิ่งที่แสดงอยู่ที่นั่นโดยไม่ต้องรอ โหลดเต็ม- ข้อกำหนดกำหนดไว้หลายอย่างสำหรับฉันซึ่งไม่ใช่วิธีการทั่วไป

    เอฟเอฟ C0 00 11 08 00 10 00 10 03 01 22 00 02
    11 01 03 11 01

    ความยาว: 17 ไบต์
    ความแม่นยำ: 8 บิต ในวิธีพื้นฐานจะเป็น 8 เสมอ ตามที่ฉันเข้าใจ นี่คือความลึกบิตของค่าช่องสัญญาณ
    ความสูงของรูปภาพ: 0x10 = 16
    ความกว้างของรูป: 0x10 = 16
    จำนวนส่วนประกอบ: 3 ส่วนใหญ่มักเป็น Y, Cb, Cr

    องค์ประกอบที่ 1:
    รหัส: 1
    การทำให้ผอมบางในแนวนอน (H 1): 2
    [_2] การทำให้ผอมบางในแนวตั้ง (V 1): 2
    รหัสตารางการหาปริมาณ: 0

    องค์ประกอบที่ 2:
    รหัส: 2
    การทำให้ผอมบางในแนวนอน (H 2): 1
    [_1] การทำให้ผอมบางในแนวตั้ง (V 2): 1

    องค์ประกอบที่ 3:
    รหัส: 3
    การทำให้ผอมบางในแนวนอน (H 3): 1
    [_1] การทำให้ผอมบางในแนวตั้ง (V 3): 1
    รหัสตารางการหาปริมาณ: 1

    ตอนนี้ มาดูวิธีการพิจารณาว่าภาพมีความบางแค่ไหน เราพบ H สูงสุด =2 และ V สูงสุด =2 Channel i จะถูกทำให้บางลงโดย H max /H i คูณในแนวนอน และ V max /V i คูณในแนวตั้ง

    เครื่องหมาย: DHT (โต๊ะ Huffman)

    ส่วนนี้จะจัดเก็บรหัสและค่าที่ได้รับจากการเข้ารหัส Huffman

    เอฟเอฟ C4 00 15 00 01 01 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 03 02

    ความยาว: 21 ไบต์
    คลาส: 0 (0 - ตารางค่าสัมประสิทธิ์ DC, 1 - ตารางค่าสัมประสิทธิ์ AC)
    [_0] รหัสตาราง: 0
    ความยาวรหัสฮัฟฟ์แมน: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
    จำนวนรหัส:
    จำนวนรหัสหมายถึงจำนวนรหัสที่มีความยาวนั้น โปรดทราบว่าส่วนนี้จะจัดเก็บเฉพาะความยาวของรหัสเท่านั้น ไม่ใช่ตัวรหัสเอง เราต้องหารหัสด้วยตัวเอง ดังนั้นเราจึงมีหนึ่งรหัสที่มีความยาว 1 และอีกหนึ่งรหัสที่มีความยาว 2 รวม 2 รหัส ไม่มีรหัสอีกต่อไปในตารางนี้
    แต่ละรหัสมีค่าที่เกี่ยวข้องกัน และมีการระบุไว้ในไฟล์ดังต่อไปนี้ ค่าเป็นไบต์เดียวดังนั้นเราจึงอ่านได้ 2 ไบต์
    - ค่าของรหัสที่ 1
    - ค่าของรหัสที่ 2

    การก่อสร้างแผนผังรหัส Huffman

    เราต้องสร้างไบนารีทรีจากตารางที่เราได้รับในส่วน DHT และจากแผนผังนี้ เราจดจำแต่ละโค้ดได้ เราเพิ่มค่าตามลำดับที่ระบุไว้ในตาราง อัลกอริธึมนั้นเรียบง่าย: ไม่ว่าเราจะอยู่ในโหนดใดก็ตาม เรามักจะพยายามเพิ่มค่าให้กับสาขาด้านซ้ายเสมอ และถ้าเธอยุ่งก็ไปทางขวา และหากไม่มีที่ว่างให้เราก็กลับไปสู่ระดับที่สูงกว่าแล้วลองจากที่นั่น คุณต้องหยุดที่ระดับ เท่ากับความยาวรหัส. กิ่งด้านซ้ายตรงกับค่า 0 กิ่งด้านขวา - 1
    ความคิดเห็น:
    คุณไม่จำเป็นต้องเริ่มจากด้านบนทุกครั้ง เพิ่มมูลค่า - กลับสู่ระดับที่สูงขึ้น มีสาขาที่ถูกต้องหรือไม่? ถ้าใช่ก็ขึ้นไปอีกครั้ง ถ้าไม่เช่นนั้น ให้สร้างสาขาที่ถูกต้องแล้วไปที่นั่น จากนั้นจากจุดนี้ให้เริ่มค้นหาเพื่อเพิ่มค่าถัดไป

    ต้นไม้สำหรับตารางทั้งหมดในตัวอย่างนี้:


    UPD (ขอบคุณ anarsoul): โหนดของทรีแรก (DC, id =0) ต้องมีค่า 0x03 และ 0x02

    ในวงกลมคือความหมายของรหัส ใต้วงกลมคือรหัสต่างๆ (ให้ฉันอธิบายว่าเราได้มันมาจากการไปตามเส้นทางจากด้านบนไปยังแต่ละโหนด) ด้วยรหัสเหล่านี้ (ของตารางนี้และตารางอื่น ๆ ) จึงมีการเข้ารหัสเนื้อหาของรูปภาพ

    เครื่องหมาย: SOS (เริ่มการสแกน)

    ไบต์ในเครื่องหมายหมายถึง “ใช่! ในที่สุด เราก็ย้ายไปที่การแยกวิเคราะห์ส่วนภาพที่เข้ารหัสโดยตรง!” อย่างไรก็ตาม ส่วนนี้มีชื่อเรียกในเชิงสัญลักษณ์ว่า SOS

      FF DA 00 0C 03 01 00 02 11
    03 11 00 3F 00

    ความยาวของส่วนหัว (ไม่ใช่ทั้งส่วน): 12 ไบต์
    จำนวนส่วนประกอบการสแกน เรามี 3 อัน อย่างละอันสำหรับ Y, Cb, Cr

    องค์ประกอบที่ 1:
    หมายเลขส่วนประกอบภาพ: 1 (Y)
    รหัสตาราง Huffman สำหรับค่าสัมประสิทธิ์ DC: 0
    [_0] รหัสตาราง Huffman สำหรับค่าสัมประสิทธิ์ AC: 0

    องค์ประกอบที่ 2:
    หมายเลขส่วนประกอบของภาพ: 2 (Cb)

    [_1]

    องค์ประกอบที่ 3:
    หมายเลขส่วนประกอบภาพ: 3 (Cr)
    รหัสตาราง Huffman สำหรับค่าสัมประสิทธิ์ DC: 1
    [_1] รหัสตาราง Huffman สำหรับค่าสัมประสิทธิ์ AC: 1

    ส่วนประกอบเหล่านี้สลับกันเป็นวงกลม

    นี่คือจุดที่ส่วนหัวสิ้นสุด จากที่นี่ไปสิ้นสุด (เครื่องหมาย) คือข้อมูลที่เข้ารหัส


    0

    การหาค่าสัมประสิทธิ์กระแสตรง
    1. การอ่านลำดับของบิต (หากเราพบ 2 ไบต์แสดงว่านี่ไม่ใช่เครื่องหมาย แต่เป็นเพียงไบต์)- หลังจากแต่ละบิต เราจะเคลื่อนที่ไปตามแผนผัง Huffman (พร้อมตัวระบุที่เกี่ยวข้อง) ไปตามสาขา 0 หรือ 1 ขึ้นอยู่กับบิตที่อ่าน เราหยุดถ้าเราพบว่าตัวเองอยู่ใน โหนดสิ้นสุด.
    10 1011101110011101100001111100100

    2. เรารับค่าของโหนด ถ้ามันเท่ากับ 0 สัมประสิทธิ์จะเท่ากับ 0 เราเขียนมันลงในตารางและอ่านค่าสัมประสิทธิ์อื่นต่อไป ในกรณีของเรา - 02 ค่านี้คือความยาวของสัมประสิทธิ์เป็นบิต นั่นคือเราอ่านอีก 2 บิตถัดไป นี่จะเป็นค่าสัมประสิทธิ์
    10 10 11101110011101100001111100100

    3. ถ้าตัวเลขตัวแรกของค่าเข้า การเป็นตัวแทนไบนารี- 1 แล้วปล่อยไว้เหมือนเดิม: DC_coef = value มิฉะนั้น เราจะแปลง: DC_coef = value-2 value length +1 เราเขียนค่าสัมประสิทธิ์ลงในตารางที่จุดเริ่มต้นของซิกแซก - มุมซ้ายบน

    การหาค่าสัมประสิทธิ์ไฟฟ้ากระแสสลับ
    1. คล้ายกับขั้นตอนที่ 1 การหาค่าสัมประสิทธิ์ DC เราอ่านลำดับต่อไป:
    10 10 1110 1110011101100001111100100

    2. เรารับค่าของโหนด หากเป็น 0 แสดงว่าค่าที่เหลือของเมทริกซ์ต้องเต็มไปด้วยศูนย์ จากนั้นเมทริกซ์ถัดไปจะถูกเข้ารหัส สองสามคนแรกที่อ่านมาไกลขนาดนี้และเขียนถึงฉันเกี่ยวกับเรื่องนี้ในข้อความส่วนตัวจะได้รับข้อดีในเรื่องกรรม ในกรณีของเรา ค่าโหนดคือ 0x31
    แทะแรก: 0x3 - นี่คือจำนวนศูนย์ที่เราต้องเพิ่มลงในเมทริกซ์ เหล่านี้คือ 3 ค่าสัมประสิทธิ์เป็นศูนย์
    แทะที่สอง: 0x1 - ความยาวสัมประสิทธิ์เป็นบิต อ่านตอนต่อไปหน่อย
    10 10 1110 1 110011101100001111100100

    3. คล้ายกับขั้นตอนที่ 3 ในการหาค่าสัมประสิทธิ์กระแสตรง

    ดังที่คุณเข้าใจแล้ว คุณต้องอ่านค่าสัมประสิทธิ์ AC จนกว่าเราจะเจอ ค่าว่างรหัสหรือจนกว่าเมทริกซ์จะเต็ม
    ในกรณีของเราเราจะได้รับ:
    10 10 1110 1 1100 11 101 10 0 0 0 1 11110 0 100
    และเมทริกซ์:





    คุณสังเกตเห็นว่าค่าต่างๆ ถูกกรอกในรูปแบบซิกแซกเดียวกันหรือไม่?
    เหตุผลในการใช้ลำดับนี้เป็นเรื่องง่าย - เนื่องจากยิ่งค่า v และ u มากขึ้น ค่าสัมประสิทธิ์ S vu ที่มีนัยสำคัญน้อยกว่าก็จะอยู่ในการแปลงโคไซน์แบบไม่ต่อเนื่อง ดังนั้นเมื่อ ระดับสูงการบีบอัดค่าสัมประสิทธิ์ที่ไม่มีนัยสำคัญถูกตั้งค่าเป็นศูนย์ซึ่งจะช่วยลดขนาดไฟล์

    [-4 1 1 1 0 0 0 0] [ 5 -1 1 0 0 0 0 0]
    [ 0 0 1 0 0 0 0 0] [-1 -2 -1 0 0 0 0 0]
    [ 0 -1 0 0 0 0 0 0] [ 0 -1 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [-1 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]

    [-4 2 2 1 0 0 0 0]
    [-1 0 -1 0 0 0 0 0]
    [-1 -1 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]

    โอ้ฉันลืมบอกว่าค่าสัมประสิทธิ์ DC ที่เข้ารหัสไม่ใช่ค่าสัมประสิทธิ์ DC แต่เป็นความแตกต่างระหว่างค่าสัมประสิทธิ์ของตารางก่อนหน้า (ช่องเดียวกัน)! เมทริกซ์จะต้องได้รับการแก้ไข:
    กระแสตรงที่สอง: 2 + (-4) = -2
    กระแสตรงที่ 3: -2 + 5 = 3
    DC ที่ 4: 3 + (-4) = -1

    [-2 1 1 1 0 0 0 0] [ 3 -1 1 0 0 0 0 0] [-1 2 2 1 0 0 0 0]
    ………

    ตอนนี้ทุกอย่างเป็นไปตามลำดับ กฎนี้ใช้จนกระทั่งสิ้นสุดไฟล์

    ...และตามเมทริกซ์สำหรับ Cb และ Cr:

    [-1 0 0 0 0 0 0 0]
    [ 1 1 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]

    เนื่องจากมีเมทริกซ์เพียงเมทริกซ์เดียว ค่าสัมประสิทธิ์ DC จึงไม่ถูกแตะต้อง

    การคำนวณ

    การหาปริมาณ

    คุณจำได้ไหมว่าเมทริกซ์ต้องผ่านขั้นตอนการหาปริมาณ องค์ประกอบของเมทริกซ์จะต้องคูณทีละเทอมด้วยองค์ประกอบของเมทริกซ์เชิงปริมาณ สิ่งที่เหลืออยู่คือการเลือกสิ่งที่คุณต้องการ ขั้นแรกเราสแกนส่วนประกอบแรก ส่วนประกอบรูปภาพ = 1 ส่วนประกอบรูปภาพที่มี ID นี้ใช้เมทริกซ์การหาปริมาณเป็น 0 (ของเราคือตัวแรกในสอง) ดังนั้นหลังจากการคูณ:


    [ 0 120 280 0 0 0 0 0]
    [ 0 -130 -160 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]

    ในทำนองเดียวกัน เราได้เมทริกซ์ Y-channel อีก 3 ตัว...

    [-320 110 100 160 0 0 0 0] [ 480 -110 100 0 0 0 0 0]
    [ 0 0 140 0 0 0 0 0] [-120 -240 -140 0 0 0 0 0]
    [ 0 -130 0 0 0 0 0 0] [ 0 -130 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [-140 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]

    [-160 220 200 160 0 0 0 0]
    [-120 0 -140 0 0 0 0 0]
    [-140 -130 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]

    ...และโดยเมทริกซ์สำหรับ Cb และ Cr

    [-170 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 180 210 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]
    [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0]

    การแปลงโคไซน์แบบไม่ต่อเนื่องผกผัน

    สูตรไม่ควรยากเกินไป*. S vu คือเมทริกซ์สัมประสิทธิ์ผลลัพธ์ของเรา คุณ - คอลัมน์, v - แถว s yx - ค่าช่องสัญญาณโดยตรง

    *โดยทั่วไปแล้ว สิ่งนี้ไม่เป็นความจริงทั้งหมด เมื่อฉันสามารถถอดรหัสและแสดงภาพขนาด 16x16 บนหน้าจอได้ ฉันก็ถ่ายภาพขนาด 600x600 ขึ้นมา (อย่างไรก็ตาม นี่คือหน้าปกอัลบั้มโปรดของ Mind.In.A.Box - Lost Alone) มันไม่ได้ผลทันที - มีข้อบกพร่องต่างๆ เกิดขึ้น ในไม่ช้าฉันก็สามารถชื่นชมภาพที่โหลดอย่างถูกต้อง สิ่งเดียวที่ทำให้ฉันเสียใจมากคือความเร็วในการโหลด ฉันยังจำได้ว่ามันใช้เวลา 7 วินาที แต่นี่ก็ไม่น่าแปลกใจหากคุณใช้สูตรข้างต้นโดยไม่ได้ตั้งใจในการคำนวณหนึ่งช่องของหนึ่งพิกเซลคุณจะต้องค้นหา 128 โคไซน์ การคูณ 768 และการบวกบางอย่าง ลองคิดดูสิ - การดำเนินการที่ยากลำบากเกือบพันรายการบนช่องสัญญาณเดียวที่มีพิกเซลเดียว! โชคดีที่ยังมีพื้นที่สำหรับการเพิ่มประสิทธิภาพ (หลังจากการทดลองหลายครั้ง ฉันลดเวลาในการโหลดลงเหลือขีดจำกัดความแม่นยำของตัวจับเวลาที่ 15 มิลลิวินาที และหลังจากนั้น ฉันเปลี่ยนรูปภาพเป็นภาพถ่ายที่มีพื้นที่ใหญ่ขึ้น 25 เท่า บางทีฉันจะเขียนเกี่ยวกับเรื่องนี้ใน บทความแยกต่างหาก)

    ฉันจะเขียนผลลัพธ์ของการคำนวณเฉพาะเมทริกซ์แรกของช่อง Y (ค่าจะถูกปัดเศษ):


    [ 87 72 50 36 37 55 79 95]
    [-10 5 31 56 71 73 68 62]
    [-87 -50 6 56 79 72 48 29]

    และที่เหลืออีก 2:
    Cr.ซีบี
    [ 60 52 38 20 0 -18 -32 -40] [ 19 27 41 60 80 99 113 120]
    [ 48 41 29 13 -3 -19 -31 -37] [ 0 6 18 34 51 66 78 85]
    [ 25 20 12 2 -9 -19 -27 -32] [-27 -22 -14 -4 7 17 25 30]
    [ -4 -6 -9 -13 -17 -20 -23 -25] [-43 -41 -38 -34 -30 -27 -24 -22]
    [ -37 -35 -33 -29 -25 -21 -18 -17] [-35 -36 -39 -43 -47 -51 -53 -55]
    [ -67 -63 -55 -44 -33 -22 -14 -10] [ -5 -9 -17 -28 -39 -50 -58 -62]
    [ -90 -84 -71 -56 -39 -23 -11 -4] [ 32 26 14 -1 -18 -34 -46 -53]
    [-102 -95 -81 -62 -42 -23 -9 -1] [ 58 50 36 18 -2 -20 -34 -42]

    1. โอเค ฉันจะไปกิน!
    2. ใช่ ฉันไม่ย้ายเข้าเลย เรากำลังพูดถึงเรื่องอะไร
    3. เมื่อได้รับค่าสี YCbCr แล้ว สิ่งที่เหลืออยู่คือการแปลงเป็น RGB เช่นนี้: YCbCrToRGB(Y ij , Cb ij , Cr ij) , Y ij , Cb ij , Cr ij - เมทริกซ์ผลลัพธ์ของเรา
    4. เมทริกซ์ Y 4 ตัว และ Cb และ Cr อย่างละหนึ่งตัว เนื่องจากเราลดขนาดช่องสัญญาณลงและพิกเซล Y 4 ตัวจะสอดคล้องกับ Cb และ Cr หนึ่งตัว ดังนั้น ให้คำนวณดังนี้: YCbCrToRGB(Y ij , Cb , Cr )
    หากคุณเลือกข้อ 1 และ 4 ฉันยินดีกับคุณ ไม่ว่าคุณจะทำถูกต้องหรือคุณจะเพลิดเพลินกับอาหารของคุณในไม่ช้า

    YCbCr เป็น RGB

    R = Y + 1.402 * Cr
    G = Y - 0.34414 * Cb - 0.71414 * Cr
    B = Y + 1.772 * Cb
    อย่าลืมบวก 128 หากค่าเกินช่วงเวลา ให้กำหนดค่าขอบเขต สูตรนี้เรียบง่ายแต่ยังกินส่วนแบ่งเวลาประมวลผลอีกด้วย

    ต่อไปนี้เป็นตารางผลลัพธ์สำหรับช่อง R, G, B สำหรับสี่เหลี่ยมด้านซ้ายบนขนาด 8x8 ตามตัวอย่างของเรา:
    255 248 194 148 169 215 255 255
    255 238 172 115 130 178 255 255
    255 208 127 59 64 112 208 255
    255 223 143 74 77 120 211 255
    237 192 133 83 85 118 184 222
    177 161 146 132 145 162 201 217
    56 73 101 126 144 147 147 141
    0 17 76 126 153 146 127 108

    231 185 117 72 67 113 171 217
    229 175 95 39 28 76 139 189
    254 192 100 31 15 63 131 185
    255 207 115 46 28 71 134 185
    255 241 175 125 112 145 193 230
    226 210 187 173 172 189 209 225
    149 166 191 216 229 232 225 220
    72 110 166 216 238 231 206 186

    255 255 249 203 178 224 255 255
    255 255 226 170 140 187 224 255
    255 255 192 123 91 138 184 238
    255 255 208 139 103 146 188 239
    255 255 202 152 128 161 194 232
    255 244 215 200 188 205 210 227
    108 125 148 172 182 184 172 167
    31 69 122 172 191 183 153 134

    จบ

    โดยทั่วไปแล้ว ฉันไม่ใช่ผู้เชี่ยวชาญด้าน JPEG ดังนั้นฉันจึงไม่น่าจะสามารถตอบคำถามทั้งหมดได้ เพียงแต่ว่าตอนที่ฉันเขียนตัวถอดรหัส ฉันมักจะต้องจัดการกับปัญหาต่างๆ ที่ไม่อาจเข้าใจได้ และเมื่อแสดงภาพไม่ถูกต้องฉันก็ไม่รู้ว่าฉันทำผิดตรงไหน บางทีเขาอาจจะตีความบิตไม่ถูกต้อง หรือบางทีเขาอาจใช้ DCT ไม่ถูกต้อง ฉันคิดถึงมันจริงๆ ตัวอย่างทีละขั้นตอนหวังว่าบทความนี้จะช่วยได้เมื่อเขียนตัวถอดรหัส ฉันคิดว่ามันครอบคลุมคำอธิบาย วิธีการพื้นฐานแต่ถึงกระนั้นคุณก็ไม่สามารถผ่านแค่เธอไปได้ ฉันเสนอลิงก์ที่ช่วยฉัน: