เทคนิคการอ่าน QR code โดยไม่ใช้คอมพิวเตอร์
(qr.blinry.org)- สรุปขั้นตอนทีละขั้นสำหรับถอดรหัส QR code ด้วยมือ ตั้งแต่โครงสร้าง โมดูล 21×21 ของเวอร์ชัน 1 ไปจนถึงการถอด mask และแปลงเป็น byte
- พื้นที่พิเศษ เช่น finder pattern, timing pattern, format information และ quiet zone จำเป็นต่อการรู้จำ แต่ต้องข้ามเมื่ออ่านข้อมูลจริง
- ข้อมูลจะถูกกู้คืนหลังตรวจสอบ mask pattern และระดับ error correction จาก format information แล้วกลับค่าโมดูลของ QR code ในตำแหน่งที่เป็นโมดูลสีดำของ mask
- เริ่มจากมุมขวาล่าง อ่านทีละสองคอลัมน์ตาม ลำดับซิกแซก และในโหมด Byte กลุ่ม 8 บิตหลังความยาว 8 บิตจะกลายเป็น byte ของตัวอักษร
- ไม่จำเป็นต้องแก้ส่วน error correction ด้วยมือ สำหรับ QR code แบบง่าย สามารถถอดรหัสได้โดยอ่าน byte ตามจำนวนที่ฟิลด์ความยาวระบุ แล้วแปลงด้วยตาราง ASCII
เตรียม QR code สำหรับอ่านด้วยมือ
- QR code สำหรับฝึกสามารถเตรียมได้สามวิธี
- ป้อนข้อความใดก็ได้เพื่ออัปเดต QR code ที่จะอธิบายด้านล่าง
- เรียนรู้วิธีอ่านโดยสแกน QR code ที่มีอยู่ด้วยกล้อง
- ฝึกด้วยคำภาษาอังกฤษแบบสุ่ม โดยคำจะไม่แสดง จึงใช้เป็นแบบฝึกได้
- QR code ตัวอย่างมีขนาด 21×21 โมดูล
- หน่วยใน QR code ที่เทียบได้กับพิกเซลเรียกว่า โมดูล (module)
- ขนาดของ QR code แบ่งตาม เวอร์ชัน (version)
- เวอร์ชันที่เล็กที่สุดคือ 21×21 โมดูล
- ในเวอร์ชันถัด ๆ ไป ความยาวด้านหนึ่งจะเพิ่มขึ้นครั้งละ 4
- QR code ขนาด 21×21 โมดูลคือเวอร์ชัน 1
พื้นที่พิเศษที่ต้องข้ามใน QR code
- finder pattern ช่วยให้สแกนเนอร์ระบุ QR code ได้ก่อน
- เส้นว่างรอบ finder pattern ต้องข้ามเมื่ออ่านเนื้อหา
- QR code เวอร์ชัน 1 ไม่มี alignment pattern
- alignment pattern เป็นแพตเทิร์นเพิ่มเติมที่ช่วยให้สแกนเนอร์อ่าน QR code ได้ถูกต้อง
- timing pattern คือสองเส้นที่โมดูลขาวดำสลับกันเสมอ ช่วยให้สแกนเนอร์อ่าน QR code ได้ถูกต้อง
- format information ใช้กำหนด mask pattern และ ระดับ error correction
- มี format information แนวตั้งและแนวนอน
- timing pattern จะตัดผ่านทั้งสองเส้น
- quiet zone คือขอบสีขาวรอบ QR code
- ช่วยให้สแกนเนอร์ระบุจุดเริ่มต้นและจุดสิ้นสุดของ QR code
การถอด mask pattern
- QR code ใช้ mask เพื่อหลีกเลี่ยงกลุ่มสีดำหรือสีขาวขนาดใหญ่
- mask มีตัวเลือกทั้งหมด 8 แบบ
- ในตัวอย่าง จะอ่านโมดูลสีดำเป็น 1 และโมดูลสีขาวเป็น 0 เพื่อตรวจสอบบิตของ mask pattern
- บิตตัวอย่างคือเลขฐานสอง
110 110เท่ากับเลขฐานสิบ 6
- บิตตัวอย่างคือเลขฐานสอง
- mask แต่ละประเภทมีแพตเทิร์นที่กำหนดไว้ล่วงหน้า
- แพตเทิร์นของ QR code ตัวอย่างดูเหมือน ส่วนหนึ่งของสายรุ้งขาวดำ
- วาง mask ซ้ำ ๆ บนพื้นที่ข้อมูล แล้วกลับค่าโมดูลของ QR code ทุกตำแหน่งที่เป็นโมดูลสีดำใน mask
- มี DIY zine ที่รวมชีตสรุปของ mask ทุกประเภทไว้ให้
- ดูตัวอย่างการพับเป็นสมุดเล่มเล็กได้จาก ภาพคำแนะนำนี้
โหมดการเข้ารหัสและลำดับการอ่าน
- การถอดรหัสเนื้อหาเริ่มจากการตรวจสอบ โหมดการเข้ารหัส ก่อน
- ข้อมูลการเข้ารหัสจะอยู่ที่มุมขวาล่างเสมอ
- ต้องใช้ mask เพื่อถอดข้อมูลโหมดการเข้ารหัสก่อนเช่นกัน
- ในตัวอย่าง ให้ดูชีตสรุปแล้ว XOR สองช่อง
- โหมดการเข้ารหัสมี Numeric, Alphanumeric, Byte, ECI, Kanji เป็นต้น
- โหมดการเข้ารหัสของ QR code ตัวอย่างคือ Byte(4)
- เนื้อหาเริ่มจากมุมขวาล่าง
- อ่านขึ้นแบบซิกแซกระหว่างสองคอลัมน์
- จากนั้นอ่านลงแบบซิกแซกในสองคอลัมน์ถัดไปทางซ้าย
- ต้องข้ามพื้นที่พิเศษทั้งหมดเสมอ
การถอดรหัสความยาวและ byte
- 4 บิตแรกคือโหมดการเข้ารหัส
- ในโหมด Byte 8 บิตถัดไปจะระบุความยาวของเนื้อหา
- หลังจากนั้น ทุก ๆ 8 บิตจะเป็น byte ของเนื้อหา 1 byte
- ข้อมูลความยาวก็ต้องใช้ mask เพื่อถอดเช่นกัน
- ข้อมูลความยาวที่ถอด mask แล้วในตัวอย่างคือ
00001100- เป็นเลขฐานสิบ
12 - หมายความว่าความยาวเนื้อหาทั้งหมดคือ 12 byte
- เป็นเลขฐานสิบ
- byte แรกที่ถอด mask แล้วคือ
01001000- เป็นเลขฐานสิบหก
0x48 - อักขระ ASCII ที่สอดคล้องกันคือ
H
- เป็นเลขฐานสิบหก
- byte ที่สองที่ถอด mask แล้วคือ
01100101- เป็นเลขฐานสิบหก
0x65 - อักขระ ASCII ที่สอดคล้องกันคือ
e
- เป็นเลขฐานสิบหก
- byte ที่เหลือถูกเว้นไว้เป็นแบบฝึก และสามารถหยุดได้เมื่ออ่านครบจำนวนอักขระตามที่ฟิลด์ความยาวก่อนหน้าระบุ
ตาราง ASCII และ error correction
- สามารถใช้ตาราง ASCII เพื่อแปลง ค่าเลขฐานสิบหก เป็นอักขระได้
- ตัวพิมพ์เล็กเริ่มจาก
aที่0x61และจบที่zที่0x7A- อักขระตรงกลางสามารถนับเพื่อหาได้
- พื้นที่ที่เหลือทั้งหมดไม่ได้เป็นเนื้อหาเสมอไป
- QR code ยังมี error correction รวมอยู่ด้วย
- ช่วยให้อ่าน QR code ได้แม้บางส่วนเสียหาย เบลอ หรือหายไป
- error correction ถูกสร้างด้วยคณิตศาสตร์ แต่ไม่ครอบคลุมในจุดประสงค์ของการอ่านด้วยมือ
- หลังจากเรียนรู้ขั้นตอนถอดรหัส QR code แบบง่ายด้วยมือแล้ว สามารถฝึกคำภาษาอังกฤษสั้น ๆ ด้วยปุ่มสุ่มโค้ด หรือสแกน QR code จริงด้วยปุ่ม Scan code ได้
- ซอร์สโค้ดอยู่ที่ Codeberg
- ยินดีต้อนรับ PR ที่อธิบายโหมดการเข้ารหัส UTF-8 เป็นพิเศษ
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ช่วงปลายยุค 90 หรือต้นยุค 2000 ผมอยากย้ายข้อมูลใน ดิสก์ Atari 8-bit ไปไว้บนพีซี
ผมรู้จักสาย SIO2PC และซอฟต์แวร์ที่ใช้เชื่อมพอร์ต SIO ของ Atari กับพอร์ตอนุกรมของพีซีอยู่แล้ว แต่ตอนนั้นยังไม่มีทักษะอิเล็กทรอนิกส์พอจะทำเอง
สุดท้ายเลยเขียนโปรแกรม Basic บน Atari ให้อ่านดิสก์ทีละเซกเตอร์ แล้ววาดลงหน้าจอด้วยพิกเซล 4 สีขนาดใหญ่ใน graphics mode 3 จากนั้นต่อ Atari เข้ากับการ์ดทีวีของพีซี แล้วใช้โปรแกรม Delphi จับภาพหน้าจอรัว ๆ เพื่อถอดรหัสข้อมูล
เพราะเซกเตอร์ว่างทำให้การจัดตำแหน่งพิกเซลเพี้ยน ผมจึงใส่ทั้งแพตเทิร์นมาสก์ เช็กซัม และที่อยู่เซกเตอร์ลงไปด้วย และด้วยวิธีนั้นก็ย้ายข้อมูลทั้งดิสก์ไปยังพีซีได้สำเร็จ
ทุกวันนี้ผมยังถือว่านี่คือ ความสำเร็จทางวิศวกรรมที่ดีที่สุด ของตัวเอง
ราว 10 ปีต่อมาผมได้สร้างโปรแกรม SIO2PC ชื่อ AspeQt และฟอร์กจากชุมชนที่ใหม่กว่าชื่อ RespeQt ก็ยังเป็นเครื่องมือที่คนใช้กันมากที่สุดในสายนี้ พร้อมทั้งมีซับฟอรัมเฉพาะบน AtariAge ด้วย: https://forums.atariage.com/forum/184-respeqt-sio2pc-softwar...
ว่ากันว่าใช้ไฟแบ็กไลต์ของ LCD กระพริบเป็นแพตเทิร์นบิต แล้วใช้กล้องอ่านข้อมูลนั้นออกมา: https://mastodon.social/@bagder/111538350617290554
คำอธิบายที่ว่า “การแก้ไขข้อผิดพลาดเป็นคณิตศาสตร์ซับซ้อน เลยไม่สนเวลาจะอ่านด้วยมือ” น่าจะอธิบายเพิ่มอีกหน่อย
ผมเข้าใจว่าคณิตศาสตร์มันยาก แต่ก็ยังอยากรู้ว่า ข้อมูลสำหรับแก้ไขข้อผิดพลาด ถูกต่อไว้ท้ายข้อมูล ใส่หลังทุกไบต์ หรือแทรกอยู่ตรงกลางกันแน่
และถ้าเป็น QR code ที่ไม่เสียหายเลย ก็อยากรู้เหมือนกันว่าต่อให้มีการแก้ไขข้อผิดพลาด เราจะยังอ่านด้วยมือได้ไหมโดยข้ามแค่ส่วนคณิตศาสตร์นั้นไป
% 10จนได้ค่า 0 ถึง 9เพราะงั้นถึงข้อมูลจะผิด ก็ยังมีโอกาส 1 ใน 10 ที่เช็กซัมจะบังเอิญตรงอยู่ดี และอย่างไรก็ดีตัวเลขตัวสุดท้ายก็ไม่สำคัญต่อ ID บาร์โค้ดสินค้าจริง ๆ
ครั้งหนึ่งตอนผมจะคืนของที่ Home Depot บาร์โค้ดขาดจนเลขเช็กซัมหลุดหายไป ผมเลยรีบสุดชีวิตเพื่อจะคำนวณมันก่อนที่พนักงานจะค้นหาแบบแมนนวล แต่สุดท้ายพนักงานชนะ และผมก็ยังลืมไม่ลง
https://www.gs1.org/services/how-calculate-check-digit-manua...
https://www.simplybarcodes.com/barcode_check_digit_calculato...
จากนั้นจะแบ่งสตรีมบิตออกเป็นบล็อกตามขนาดและระดับการแก้ไขข้อผิดพลาด คำนวณข้อมูลแก้ไขข้อผิดพลาดสำหรับแต่ละบล็อก แล้วนำบล็อกมาอินเตอร์ลีฟ
เพราะฉะนั้นวิธีนี้จะใช้ไม่ได้กับ QR version 5 ขึ้นไปไม่ว่าระดับการแก้ไขข้อผิดพลาดจะเป็นเท่าไร และใน version 3–5 ก็จะใช้ไม่ได้ถ้าตั้งระดับการแก้ไขข้อผิดพลาดสูง
ในความเป็นจริง จะมีการใช้โค้ดอยู่สองแบบที่ต่างกันเล็กน้อยคือ Reed-Solomon และ BCH ตามชนิดของข้อมูล
https://www.quaxio.com/an_artisanal_qr_code.html
โพสต์ที่เกี่ยวข้อง:
Decoding small QR codes by hand (2012) - https://news.ycombinator.com/item?id=36173441 - มิถุนายน 2023, ความคิดเห็น 69 รายการ
How a QR code works - https://news.ycombinator.com/item?id=32837565 - กันยายน 2022, ความคิดเห็น 114 รายการ
Creating a QR Code step by step - https://news.ycombinator.com/item?id=24119124 - สิงหาคม 2020, ความคิดเห็น 41 รายการ
Creating a QR Code step by step - https://news.ycombinator.com/item?id=18360847 - พฤศจิกายน 2018, ความคิดเห็น 34 รายการ
ตัวบทความเองก็ดีมากอยู่แล้ว แต่ที่เจ๋งยิ่งกว่าคือมัน สร้างภาพทุกภาพแบบไดนามิก ตามค่าที่ป้อนเข้าไป
คำอธิบายวิธีอ่าน QR code นั้นดีมาก และถ้าจะหาอ่านเรื่องการถอดรหัส บาร์โค้ดหนึ่งมิติ ทั่วไปอย่าง UPC บทความนี้ก็ใช้ได้เหมือนกัน:
https://scanbot.io/blog/how-do-barcodes-work/
เมื่อราว 10 ปีก่อนเคยพยายามอ่าน QR code ด้วยตาเปล่า แต่ยอมแพ้เพราะ mask pattern
ต้องนำ mask pattern มาใช้ด้วย XOR ก่อน แม้กระทั่งก่อนจะรู้ชนิดข้อมูล
เลยสงสัยว่า mask pattern นี้ช่วยตัวอ่าน QR code จริง ๆ ได้มากแค่ไหน
เดือนที่แล้วลองหาการตั้งค่า error correction ที่เหมาะที่สุด แต่ถ้าเป็นกรณีที่ไม่เสียหายเลยเหมือนเมทริกซ์สมบูรณ์ที่แสดงบนหน้าจอ คำตอบกลับเป็น “ไม่มี” และกว่าจะได้ข้อสรุปนี้ก็ไม่ง่าย
หาเอกสารที่เปรียบเทียบการตั้งค่าหลายแบบกับการสแกนหลาย implementation ในสภาพแวดล้อมจริงไม่เจอ เลยลองแสดง QR ขนาดเล็กบนหน้าจอด้วยระดับ error correction ต่างกัน แล้วเขย่ากล้องเพื่อจำลองปัญหาการอ่านเอง แต่ก็ไม่เห็นความแตกต่างที่มีนัยสำคัญระหว่างแต่ละการตั้งค่า
มีทั้ง alignment marker อย่างน้อย 4 จุด มี margin กว้าง และมี timing pattern ด้วย เลยไม่แน่ใจว่าการไม่มี mask จนเกิดก้อนสีขาวใหญ่ ๆ จะสร้างความต่างได้มากจริงหรือ
เหตุผลข้อที่สองที่เลิกพยายามอ่าน QR ด้วยตาคือ โดยมากมักมี URL เขียนไว้ด้านล่างเป็นข้อความทางเลือกอยู่แล้ว แม้หลังจากนั้นจะเคยเจอกรณีที่ไม่มีข้อความทางเลือกอยู่บ้าง แต่ก็หายากมาก
ถ้าไม่ใช้ ข้อความจะกินพื้นที่น้อยลงและ QR ก็เล็กลง
ถ้าต้องให้พอดีกับพื้นที่คงที่ เช่น การพิมพ์สติกเกอร์ ก็สามารถทำให้พิกเซลมีขนาดจริงใหญ่ขึ้นได้ และสำหรับการอ่านให้เสถียร พิกเซลที่ใหญ่ขึ้น ช่วยมากกว่า error correction
บางครั้งสามารถเพิ่มระดับ error correction ได้โดยไม่ต้องเปลี่ยนขนาด QR สุดท้ายตามความยาวข้อความ ซึ่งในกรณีนั้นก็เหมือนได้ทั้งสองอย่าง
แต่มันมีไว้สำหรับคนที่ยัด URL ทั้งเส้นที่เต็มไปด้วย tracking parameter ลงใน version 25, 117x117 code แล้วเอาไปติดบนป้ายใหญ่ โดยหวังว่าข้อมูลจะยังรอดแม้มีขี้นกตกใส่หรือมีคนแปะสติกเกอร์ทับ
เป็นการทดลองเพื่อดูว่าสามารถพิมพ์ให้เล็กได้แค่ไหนแล้วยังตรวจจับได้อยู่ และก็ดูเหมือนเป็นเพราะพิกเซลแต่ละจุดใหญ่ขึ้นตามที่คอมเมนต์ข้าง ๆ ว่าไว้
วิดีโอถอดรหัส QR เมื่อราว 10 ปีก่อน: https://www.youtube.com/watch?v=KA8hDldvfv0 (20 นาที)
ผมยังมีหน้าเว็บแบบ interactive ที่สร้าง QR code ทีละขั้นตอนด้วย ซึ่งโดยพื้นฐานก็คือกระบวนการย้อนกลับ: https://www.nayuki.io/page/creating-a-qr-code-step-by-step
พอเริ่มสนใจเรื่อง error correction ก็พบว่า QR code สามารถออกแบบให้มี สัดส่วนการกู้คืนได้ ตั้งแต่ 7% ถึง 30%
น่าสนใจดี: https://docs.beaconstac.com/en/articles/6018654-what-is-erro...
Shannon ค้นพบขีดจำกัดเชิงทฤษฎีไว้ตั้งแต่กลางศตวรรษที่ 20 แต่ไม่มีใครรู้ว่าจะไปให้ถึงขีดจำกัดนั้นได้อย่างไร
พอช่วงทศวรรษ 1990 มีสิทธิบัตร turbo code ที่พาเข้าใกล้ขีดจำกัดนั้นได้อย่างกะทันหัน วงการวิชาการก็ตอบสนองแบบแทบไม่อยากเชื่อ
และแน่นอนว่าเทคโนโลยีแบบนี้เองที่ทำให้ mobile network ที่เร็วและเชื่อถือได้เกิดขึ้นได้
ใน Mystery Hunt 2023 มีปริศนาย่อยข้อหนึ่งที่ต้องถอดรหัส QR ที่พังจนแม้แต่ error correction ก็ช่วยกู้คืนไม่ได้ด้วยมือ
ผมไล่อ่านคู่มือทั้งหมดที่มีคนพูดถึงในคอมเมนต์นี้แล้ว ซึ่งก็มีประโยชน์ แต่ยังไม่ถึงกับยอดเยี่ยมมาก
เพราะงั้นการมีบทความละเอียดแบบนี้เพิ่มขึ้นจึงเป็นเรื่องดี และบทความนี้ก็ดูสมบูรณ์มากจริง ๆ
ถ้าสนใจ ปริศนาอยู่ที่นี่ และส่วนการถอดรหัส QR จะอยู่ช่วงท้าย: https://puzzles.mit.edu/2023/abcde.puzzlefactory.place/puzzl...
ดูจาก Wikipedia แล้ว QR code ถูกประดิษฐ์ขึ้นในปี 1994 โดยผู้ผลิตชิ้นส่วนรถยนต์จากญี่ปุ่นเพื่อใช้ติดฉลากชิ้นส่วนรถยนต์
เลยสงสัยว่าถ้าถูกคิดค้นในวันนี้จะทำให้ดีขึ้นได้ไหม
จะทำให้เล็กลงกว่านี้ หรืออ่านง่ายกว่านี้ได้หรือเปล่า?
ในปี 1994 บาร์โค้ดก็มีอยู่ทุกที่แล้ว แต่ก็ไม่ได้ขัดขวางไม่ให้ QR code ได้รับความนิยม
หรืออีกทางหนึ่ง อาจแทบไม่มีพื้นที่ให้ปรับปรุงแล้วก็ได้ ถ้าไม่ได้เปลี่ยนแนวคิดไปมากแบบขยับไปใช้ NFC หรืออะไรทำนองนั้น