2011-02-13 18 views
5

मैंने सुना है कि एक जेपीईजी छवि पर लापरवाही रोटेशन करना संभव होना चाहिए। इसका मतलब है कि आप एक आईडीसीटी के बिना फ्रीक्वेंसी डोमेन में रोटेशन करते हैं। मैंने इसे Google पर करने का प्रयास किया है लेकिन कुछ भी नहीं मिला है। क्या कोई इस पर कुछ प्रकाश ला सकता है?आवृत्ति डोमेन में मैं छवि को कैसे घुमा सकता हूं?

हानि रहित मेरा मतलब यह है कि मैं घूर्णन में कोई अतिरिक्त जानकारी नहीं खोता हूं। और निश्चित रूप से यह संभवतः 90 डिग्री के गुणकों को घूर्णन करते समय संभव है।

उत्तर

6

आप को किसी छवि को लापरवाही से घुमाने के लिए आईडीसीटी करने की आवश्यकता है (ध्यान दें कि रास्टर छवियों के लिए लापरवाह घूर्णन केवल 90 डिग्री के गुणक कोणों के लिए संभव है)।

लिए निम्न चरण छवि का एक स्थानांतरण को प्राप्त, डीसीटी डोमेन:

  1. प्रत्येक डीसीटी के तत्वों स्थानांतरित ब्लॉक
  2. प्रत्येक डीसीटी के पदों स्थानांतरित ब्लॉक

मैं मुझे लगता है कि आप पहले से ही निम्नलिखित कर सकते हैं:

  • कच्चे डीसीटी गुणांक को पकड़ो छवि m
  • (यदि नहीं, here देखें) गुणांक फाइल करने के लिए वापस लिखें

मैं तुम्हें पूरा कोड नहीं दिखा सकते हैं (यदि आप घुमाया छवि को बचाने के लिए चाहते हैं), यह काफी है, क्योंकि शामिल है, लेकिन यहां सा जहाँ मैं छवि IDCT है (ध्यान दें IDCT प्रदर्शन प्रयोजनों के लिए ही के लिए है):

:

Size s = coeff.size(); 
Mat result = cv::Mat::zeros(s.height, s.width, CV_8UC1); 

for (int i = 0; i < s.height - DCTSIZE + 1; i += DCTSIZE) 
for (int j = 0; j < s.width - DCTSIZE + 1; j += DCTSIZE) 
{ 
    Rect rect = Rect(j, i, DCTSIZE, DCTSIZE); 
    Mat dct_block = cv::Mat::Mat(coeff, rect); 
    idct_step(dct_block, i/DCTSIZE, j/DCTSIZE, result); 
} 

यह छवि है कि दिखाया गया है है

यहां कुछ भी फैंसी नहीं हो रही है - यह सिर्फ मूल छवि है।

transposed

आप देख सकते हैं कि छवि है:

Size s = coeff.size(); 
Mat result = cv::Mat::zeros(s.height, s.width, CV_8UC1); 

for (int i = 0; i < s.height - DCTSIZE + 1; i += DCTSIZE) 
for (int j = 0; j < s.width - DCTSIZE + 1; j += DCTSIZE) 
{ 
    Rect rect = Rect(j, i, DCTSIZE, DCTSIZE); 
    Mat dct_block = cv::Mat::Mat(coeff, rect); 
    Mat dct_bt(cv::Size(DCTSIZE, DCTSIZE), coeff.type()); 
    cv::transpose(dct_block, dct_bt);    // First transposition 
    idct_step(dct_bt, j/DCTSIZE, i/DCTSIZE, result); // Second transposition, swap i and j 
} 

इस जिसके परिणामस्वरूप छवि है:

अब, यहाँ कोड है कि दोनों स्थानांतरण चरणों मैं उपर्युक्त लागू करता है अब transposed। उचित रोटेशन प्राप्त करने के लिए, आपको प्रतिबिंब को पारदर्शिता के साथ संयोजित करने की आवश्यकता है।

संपादित

क्षमा करें, मैं भूल गया था कि प्रतिबिंब भी तुच्छ नहीं है।यह भी दो चरण होते हैं:

  1. जाहिर है, प्रत्येक डीसीटी ब्लॉक के पदों के लिए आवश्यक अक्ष में
  2. कम जाहिर है, की विपरीत (-1 से गुणा) प्रत्येक अजीब पंक्ति या प्रत्येक में स्तंभ को प्रतिबिंबित डीसीटी ब्लॉक। यदि आप लंबवत फ़्लिप कर रहे हैं, अजीब पंक्तियां उलटा करें। यदि आप क्षैतिज रूप से फ़्लिप कर रहे हैं, तो अजीब कॉलम उलटा करें।

यहां कोड है जो पारदर्शिता के बाद लंबवत प्रतिबिंब करता है।

for (int i = 0; i < s.height - DCTSIZE + 1; i += DCTSIZE) 
for (int j = 0; j < s.width - DCTSIZE + 1; j += DCTSIZE) 
{ 
    Rect rect = Rect(j, i, DCTSIZE, DCTSIZE); 
    Mat dct_block = cv::Mat::Mat(coeff, rect); 

    Mat dct_bt(cv::Size(DCTSIZE, DCTSIZE), coeff.type()); 
    cv::transpose(dct_block, dct_bt); 

    // This is the less obvious part of the reflection. 
    Mat dct_flip = dct_bt.clone(); 
    for (int k = 1; k < DCTSIZE; k += 2) 
    for (int l = 0; l < DCTSIZE; ++l) 
     dct_flip.at<double>(k, l) *= -1; 

    // This is the more obvious part of the reflection. 
    idct_step(dct_flip, (s.width - j - DCTSIZE)/DCTSIZE, i/DCTSIZE, result); 
} 

यहाँ छवि आप प्राप्त होते हैं:

final

आप देखेंगे कि यह 90 डिग्री वामावर्त से एक रोटेशन का गठन किया।

+1

jpegtran http://jpegclub.org/jpegtran/ नामक एक प्रोग्राम libjpeg http://jpegclub.org – datenwolf

+0

में एक बहुत अच्छा स्पष्टीकरण के लिए धन्यवाद शामिल है। – onemasse

+0

@ डेटनवॉल्फ: धन्यवाद। खुद को रोल करने के बजाय इसका उपयोग करने के लिए निश्चित रूप से बेहतर है। मज़ा के रूप में नहीं, हालांकि :) – misha

0

अस्वीकरण: :-)

वैसे मैं JPEG संपीड़न एल्गोरिथ्म केवल एक बहुत सतही स्तर पर पता है। मुझे पता है कि रिक बूथ की थोड़ी तारीख से, लेकिन उत्कृष्ट पुस्तक Inner Loops, अध्याय 17: जेपीईजी।

मेरे पास आपके प्रश्न का पूर्ण उत्तर नहीं है, बल्कि मुझे समाधान का क्या अजीब विचार है। शायद यह आपके लिए पहले से ही सहायक होगा। ईमानदार होने के लिए, मैं वास्तव में यह देखकर आश्चर्यचकित होगा कि मेरे पास यह सही है।


एक JPEG छवि के

दोषरहित रोटेशन यदि आप के बाद से है कि, एक बार आप छवि घुमाया गया है फिर से यह पहली बार एक IDCT का उपयोग कर डिकोड, और उसके बाद फिर से एनकोड करने के लिए यह नहीं होगा ही संभव लगता है दो कम्प्यूटेशनल कदम जहां सूचना हानि हो सकती है।

यह बिल्कुल व्यवहार्य लगता है क्योंकि जेपीईजी के रूप में एन्कोड की गई छवि पहले ही आवृत्ति डोमेन में है, क्योंकि एक डीसीटी (असतत कोसाइन ट्रांसफॉर्म) पहले ही इस पर किया जा चुका है। मुझे उपरोक्त पुस्तक (पी। 325) से एक छोटे से पारित होने का हवाला देते हैं:

आमतौर पर डीसीटी के रूप में भेजा [है & hellip;]। संकल्पनात्मक रूप से, क्या होता है कि 8 × छवि का 8 टुकड़ा दो अन्य 8 × 8 मैट्रिक्स द्वारा व्युत्पन्न 8 × 8 मैट्रिक्स का उत्पादन करने के लिए गुणा हो जाता है। [है & hellip;]

आमतौर पर, दो 8 × 8 मैट्रिक्स गुणा 1.204 (64 2) गुणा चरणों की आवश्यकता होगी। डीसीटी के जादू का हिस्सा यह है कि इस चरण के लिए चुने गए बहुत ही विशेष मैट्रिक्स में बहुत से आंतरिक समरूपता हैं, इसलिए गणित को केवल 80 गुणा चरणों के साथ निष्पादित करने का एक तरीका है। यह समरूपता है जो जेपीईजी के लिए दिन बचाती है और एल्गोरिदम को काफी तेजी से रखती है। — (जोर मेरे द्वारा जोड़ा।)

मैं कल्पना कर सकता है कि डीसीटी परिवर्तन मैट्रिक्स में समानताएं यह संभव बाद में perceptually छवि को बदले बिना कुछ बहुत ही विशेष कोण पर तब्दील 8 × 8 मैट्रिक्स को घुमाने के लिए बनाने के (अलग तथ्य यह है कि यह निश्चित रूप से घुमाया गया है)। के बाद से मैं वास्तविक संख्यात्मक मान के बजाय

   * . . . . . . * 
       . * . . . . * . 
       . . * . . * . . 
       . . . * * . . . 
       . . . * * . . . 
       . . * . . * . . 
       . * . . . . * . 
       * . . . . . . * 

(मैं उपयोग कर रहा हूँ प्रतीक: मान लीजिए कि आप मूल 8 × 8 पिक्सेल जैसे कि निम्न मैट्रिक्स का उपयोग कर ब्लॉक बदल दिया है: एक वैचारिक स्तर पर, क्या मेरा मतलब यह है केवल इस मैट्रिक्स की समरूपता दिखाना चाहते हैं।)

इस तरह के एक परिवर्तन मैट्रिक्स पराक्रम आप किसी भी दिशा में 90 डिग्री की एक बहु से बदल मैट्रिक्स बारी बारी से करने के बाद परिवर्तन मैट्रिक्स ही हमेशा समान लगेगा अगर एक ही कोण पर बदल देते हैं।

यदि वास्तव में आप यही पढ़ते हैं, तो इसका मतलब यह होगा कि लापरवाही रोटेशन मनमाने ढंग से घूर्णन कोणों के लिए काम नहीं करेगा। कोण जो कोई नुकसान की गारंटी नहीं देते हैं वे जेपीईजी एन्कोडिंग के दौरान उपयोग की जाने वाली मैट्रिस पर निर्भर करते हैं।

+0

अच्छा, शायद मैं पर्याप्त स्पष्ट नहीं था। लापरवाही से मेरा क्या मतलब है कि मैं घूर्णन में कोई अतिरिक्त जानकारी नहीं खोता हूं। और निश्चित रूप से यह संभवतः 90 डिग्री के गुणकों को घूर्णन करते समय संभव है। – onemasse

+0

आप केवल लेंसलेस रोटेशन के बारे में सही हैं जो 90 डिग्री के बहुमत वाले कोणों के लिए संभव है, लेकिन आप आईडीसीटी चरण अनिवार्य होने के बारे में गलत हैं। – misha

+0

* @ मिशा *: यह जानना एक अच्छी बात है। क्या आप, मौके से, जेपीईजी के कामकाज के बारे में एक अच्छा दस्तावेज जानते हैं? मैं हमेशा सीखने में खुश हूं। – stakx

संबंधित मुद्दे