علوم وفضاء

packbits: هل count الكلي يزيل حشو الصفوف؟

صفوف بحدود حشو ومسار مسطح مستقل.
ثلاثة أصفار بعد كل صف؛ صفر واحد بعد المسار المسطح.

في مثالنا، فك 15 بتًا من بايتات الصفوف لم يعد البتات الأصلية.

حدد أين ينتهي الصف قبل إضافة الحشو

packbits تعمل على المحور المختار؛ axis=None يسطح المدخل، والنهاية تكتمل بأصفار. [1]

نسأل عن حدود البايت: هل تكتمل مجموعة البتات مرة في نهاية الجدول، أم بعد كل صف مستقل؟ العدد الكلي للبتات الأصلية لا يحدد وحده أين أضفنا الحشو.

في NumPy 2.3.5 على CPython 3.12.14، أنشأنا A=np.array([[1,0,0,1,1],[0,1,1,0,1],[1,1,0,0,0]],dtype=np.uint8). شكل A هو (3,5)، وعدد مواضعها 15.

نكتب الصفوف مختصرة 10011 و01101 و11000، من اليسار إلى اليمين وفق ترتيب الأعمدة. الأصفار الأخيرة في الصف الثالث عناصر أصلية، فلا نحذفها باعتبارها حشوًا.

ثبتنا bitorder="big" في التجميع والفك. نغيّر المحور وحده في المقارنة، ونستعمل أصفارًا وآحادًا مؤلفة؛ ليست هذه بطاقة ملف أو وصفًا لبيانات جهاز.

ثلاثة بايتات للصفوف وبايتان للمسار المسطح

أعطى R=np.packbits(A,axis=1,bitorder="big") القيم [[152],[104],[192]] من uint8، بالشكل (3,1). كل صف ذي خمس خانات أكملناه في مرجعنا إلى بايت مستقل بإضافة ثلاثة أصفار.

المجموعات الكاملة هي 10011000 و01101000 و11000000. نحسب أوزان الخانات الثماني في مرجعنا من 128 إلى 1: الأولى 128+16+8=152، والثانية 64+32+8=104، والثالثة 128+64=192.

أصفار الخانات الخمس الأولى في كل مجموعة من الأصل؛ أما الخانات الثلاث الأخيرة فحشو في هذه البطاقة. للصف الثالث ستة أصفار في نهاية البايت، ثلاثة منها أصلية وثلاثة حشو. نحفظ حدود الصف لتمييزهما.

في المقابل أعطى F=np.packbits(A,axis=None,bitorder="big") القيم [155,112] من uint8، بالشكل (2,). يقرأ مرجعنا الصفوف متتابعة: 10011 ثم 01101 ثم 11000، أي 100110110111000.

المجموعة الأولى لهذا المسار 10011011، والثانية 0111000 ثم صفر حشو. لذلك نحسب 128+16+8+2+1=155، و64+32+16=112. الحشو واحد عند نهاية الخمس عشرة خانة، ولم يدخل بين الصفوف الأصلية.

الصفوف المجمعة منفصلة تحمل 3×8=24 خانة بت؛ منها 15 أصلية وتسع حشو. والمسار المسطح يحمل 2×8=16 خانة؛ منها 15 أصلية وواحدة حشو. نعد بايتات الحمولة فقط، ولا نسمي هذه الأعداد حجم كائن Python أو ملف كامل.

إذن تغيرت الأعداد وعدد البايتات لأن حدود التجميع تغيرت. لم نغير ترتيب big أو القيم أو عدد البتات الأصلية عند تغيير axis.

العدد الكلي لا يحذف الأصفار الداخلية

count يحدد عدد البتات المفكوكة على المحور؛ axis=None يفك المدخل المسطح. [2]

جربنا np.unpackbits(R,axis=None,count=15,bitorder="big"). خرج متجه من 15 عنصرًا: [1,0,0,1,1,0,0,0,0,1,1,0,1,0,0]. العدد يوافق عدد عناصر A، لكن القيم لا توافق مسارها الأصلي.

لفهم السبب، نكتب بايتات R كاملة قبل أخذ المقدمة: 10011000 ثم 01101000 ثم 11000000. أخذ أول 15 خانة يحفظ البايت الأول كله وسبع خانات من الثاني؛ البايت الثالث غاب بالكامل.

في هذه المقدمة خمس خانات حشو: ثلاث بعد الصف الأول واثنتان بعد الثاني. لم يأخذ count الكلي 15 بتًا أصليًا من بين الحشو؛ أخذ مقدمة المسار الذي طلبناه. لذلك لا نعوّض حدود الصفوف بالعدد الإجمالي وحده.

أعدنا تشكيل المتجه الخاطئ إلى (3,5) للعرض فقط، فظهر [[1,0,0,1,1],[0,0,0,0,1],[1,0,1,0,0]]. الصف الأول يوافق A، والثاني والثالث مختلفان. نجاح إعادة التشكيل لأن العدد 15 لا يثبت استعادة المحتوى.

أما np.unpackbits(R,axis=1,count=5,bitorder="big") فأعاد A كاملة بالشكل (3,5) من uint8. هنا أخذنا خمس خانات من كل صف بايتات، فتركنا أصفار الحشو الثلاثة عند نهاية كل صف.

ولبايتي F، أعاد الفك مع axis=None وcount=15 البتات الأصلية المسطحة كاملة. هذا نجاح لمسار تجميع مختلف، لا نجاحًا لفك R بالطريقة نفسها؛ نكتب مصدر البايتات إلى جانب إعداد الفك.

للتحكم، أخذنا جدولًا (2,8) صفاه 10011010 و01101101. أعطى التجميع على الصفوف [[154],[109]]، والمسار المسطح [154,109]. لا توجد خانات حشو في أيهما؛ تتطابق البايتات بعد جمع صفوفها في هذا التحكم.

الاتفاق عند اكتمال الصف إلى ثماني خانات لا يلغي اختلاف المثال ذي الخمس. نحتفظ بالشكل الأصلي ومحور التجميع وترتيب البتات وعدد الخانات المطلوبة على محور الفك، قبل محاولة استعادة الجدول.

فك خاطئ بالمجموع وفك مطابق لكل صف.
count=15 للمسار الخاطئ لا يعيد الصفوف الأصلية.

مرجع الأوزان ونطاق الفحوص

بنى مرجع Python بايتًا بجمع وزن كل بت من مجموعة لا تتجاوز ثمانية، من 128 إلى 1. البتات الغائبة عند نهاية المجموعة تسهم بصفر. وللفك استخرج البت بقسمة قيمة البايت على وزنه ثم أخذ الباقي عند القسمة على اثنين.

طبق مرجع التجميع مرة على كل صف، ومرة على قائمة الصفوف المتتابعة. لا يستدعي packbits أو unpackbits في توقع القيم؛ لذلك نقارن التشغيل بعمليات مستقلة على القوائم والأوزان.

للشبكة عددنا جميع الجداول الثنائية للأشكال (2,3) و(2,5) و(3,3). أعدادها 2**6=64 و2**10=1024 و2**9=512؛ المجموع 1600، ويتضمن جدول الأصفار وجدول الآحاد لكل شكل.

لكل حالة سبعة فحوص: بايتات الصفوف وشكلها ونوعها؛ بايتات المسار المسطح وشكله ونوعه؛ الفك الصحيح لكل صف؛ الفك الصحيح للمسار المسطح؛ البتات كاملة وصفريّة الحشو؛ تعداد البايتات وخانات الحشو؛ وثبات بايتات المدخل وشكله.

أضفنا المثال (3,5) والتحكم (2,8) إلى الحالات. ثم أضفنا ثلاثة فحوص: المتجه الخاطئ ذو count=15 مقابل مرجع المقدمة؛ اختلافه عن الأصل قبل العرض وبعد إعادة التشكيل؛ وتساوي بايتات التحكم المكتمل وخلوه من الحشو.

الحساب (1600+2)×7+3=11217، ومرت جميعها. ثبات المدخل هنا يخص التشغيل المسجل؛ لا نستنتج منه ملكية الذاكرة أو أثر الكتابة إلى أي ناتج.

النطاق مدخلات uint8 ثنائية البعد، بأحجام موجبة وبتات صفرية وواحدية، وترتيب big. التجميع والفك على axis=1 أو axis=None، مع count غير سالب ومناسب للمسار المحدد.

لم نفحص مدخلًا فارغًا أو غير ثنائي أو نوعًا آخر أو little أو axis=0 أو رتبًا أعلى أو count سالبًا أو أكبر من المتاح. ولم نقس سرعة أو ذاكرة كائن أو تنسيق ملف.

المثال يبين أين جاءت الخانات الزائدة ولماذا لا يكفي العدد الكلي لإزالتها من مسار مختلف. حفظ حدود الصفوف شرط تفسير لطريقة التجميع التي اخترناها، لا تخمينًا من أصفار البايت الأخير.

مسار التجميعالشكل والبايتاتالحشو في المثالالفك المطابق
axis=1(3,1):152;104;1929 بتاتaxis=1;count=5
axis=None(2,):155;112بت واحدaxis=None;count=15

للتوسع: المحور وشكل الملخص.

المراجع

  1. NumPy 2.3 — packbits
  2. NumPy 2.3 — unpackbits

أُعدّ هذا المقال بمساعدة الذكاء الاصطناعي، وخضع لمراجعة ذاتية بالأداة نفسها. لا يُنسب إلى مراجع بشري أو خبير مستقل. منهجية المحتوى.