2025, Oct 05 13:31

Pillow affine transform में ट्रांसलेशन उलटा क्यों लगता है और सही शिफ्ट कैसे करें

जानें कि Pillow के affine transform में ट्रांसलेशन उलटा क्यों दिखता है, inverse mapping कैसे काम करता है, c के संकेत का प्रभाव, और कोड से इमेज को दाईं ओर सही तरह शिफ्ट करने का तरीका।

Pillow के affine transform से किसी इमेज को शिफ्ट करना देखने में आसान लगता है, लेकिन ट्रांसलेशन अक्सर “गलत” दिशा में चला जाता है। सकारात्मक क्षैतिज ऑफ़सेट पर उम्मीद होती है कि पिक्सेल दाईं ओर जाएँगे, जबकि आउटपुट उलटे बाईं ओर खिसकता है। असल वजह यह है कि Pillow transform के लिए affine mapping को इस तरह परिभाषित करता है: आउटपुट को इनपुट से inverse transform के जरिए सैंपल किया जाता है।

समस्या का उदाहरण

नीचे दिया गया स्निपेट इमेज को 85 पिक्सेल दाईं ओर ले जाने का इरादा रखता है। लेकिन परिणामस्वरूप कंटेंट बाईं ओर खिसकता दिखता है।

from PIL import Image
img_src = Image.open('Test image.png')
params_wrong = [1, 0, 85, 0, 1, 0]
img_shifted = img_src.transform(
    img_src.size,
    Image.AFFINE,
    params_wrong,
    Image.BILINEAR,
    fillcolor=(150, 150, 150)
)
img_shifted.save('Transformed image.png')

ऐसा क्यों होता है

Pillow के affine transform में पैरामीटर ट्यूपल (a, b, c, d, e, f) inverse transform की पहली दो पंक्तियाँ दर्शाता है। मैपिंग की दिशा आउटपुट से इनपुट की ओर होती है। आउटपुट के हर पिक्सेल (x, y) के लिए मान इनपुट के स्थान (a x + b y + c, d x + e y + f) से लिया जाता है।

यह फ़ंक्शन 6-ट्यूपल (a, b, c, d, e, f) लेता है, जो affine transform मैट्रिक्स के inverse की पहली दो पंक्तियाँ होता है। आउटपुट इमेज के प्रत्येक पिक्सेल (x, y) के लिए नया मान इनपुट इमेज में स्थिति (a x + b y + c, d x + e y + f) से लिया जाता है, जिसे निकटतम पिक्सेल तक गोल किया जाता है।

यानी c का धनात्मक होना आउटपुट को इनपुट के उन स्थानों से सैंपल करने को कहता है जो दाईं ओर खिसकाए गए हैं—नतीजतन दृश्य तौर पर कंटेंट बाईं ओर खिंच जाता है। कैनवास पर कंटेंट को दाईं तरफ ले जाने के लिए, सैंपलिंग उसी मात्रा से बाईं ओर खिसकाए गए इनपुट स्थानों से आनी चाहिए।

उपाय और सही उदाहरण

इमेज को 85 पिक्सेल दाईं ओर शिफ्ट करने के लिए c को ऋणात्मक रखें। तब आउटपुट का हर पिक्सेल (x, y) अपना मान इनपुट निर्देशांक (x − 85, y) से लेगा, और दाईं ओर का ट्रांसलेशन मिलेगा।

from PIL import Image
source_img = Image.open('Test image.png')
params_fix = [1, 0, -85, 0, 1, 0]
result_img = source_img.transform(
    source_img.size,
    Image.AFFINE,
    params_fix,
    Image.BILINEAR,
    fillcolor=(150, 150, 150)
)
result_img.save('Transformed image.png')

यह क्यों मायने रखता है

जियोमेट्रिक ट्रांसफ़ॉर्म से भ्रमित करने वाला आउटपुट समय बर्बाद करता है और प्रीप्रोसेसिंग पाइपलाइन, सिंथेटिक डेटा जेनरेशन और इमेज ऑगमेंटेशन में महीन बग्स ला सकता है। यह समझना कि Pillow का transform inverse mapping के जरिए सैंपल करता है, बताता है कि ट्रांसलेशन के संकेत उलटे क्यों लगते हैं—और कंटेंट को गलती से उलटी दिशा में खिसकाने से बचाता है।

निष्कर्ष

यदि Pillow में affine ट्रांसलेशन गलत दिशा में जा रहा हो, तो संकेत (sign) जाँचें। ट्यूपल (a, b, c, d, e, f) inverse mapping पर लागू होता है, इसलिए दाईं ओर क्षैतिज शिफ्ट के लिए c का मान ऋणात्मक होना चाहिए। यह सोचें कि आउटपुट इनपुट इमेज में कहाँ से सैंपल ले रहा है—दिशा अपने आप स्पष्ट हो जाएगी।

यह लेख StackOverflow पर प्रश्न, जिसे Christopher Pratt ने पूछा था, और J Earls के उत्तर पर आधारित है।