2012-09-19 23 views
10

मेरे पास एक वेबकैम वीडियो रिकॉर्डर प्रोग्राम है जिसमें पाइथन, ओपनसीवी और एफएमपीईपीओपनसीवी और एफएमपीपीईजी के साथ एक वीडियो बनाना। सही रंग प्रारूप कैसे ढूंढें?

यह ठीक काम करता है सिवाय इसके कि वीडियो का रंग वास्तविकता से अधिक नीला है। समस्या छवियों के रंग प्रारूप से आती है।

ऐसा लगता है कि ओपनसीवी बीजीआर छवियां दे रहा है और ffmpeg + libx264 YUV420p की अपेक्षा कर रहा है। मैंने पढ़ा है कि YUV420p YCbCr से मेल खाता है।

ओपनसीवी में बीजीआर से वाईसीबीसीआर तक कोई रूपांतरण नहीं है। यह केवल वाईसीआरसीबी में एक रूपांतरण है।

मैंने कुछ खोज की हैं और ओपनसीवी छवि को किसी ऐसे चीज़ में बदलने की कोशिश करने के लिए विभिन्न विकल्पों की कोशिश की है जो ffmpeg + libx264 के लिए ठीक हो सकता है। कोई काम नहीं कर रहा है। इस बिंदु पर, मैं थोड़ा खो गया हूं और मैं किसी भी सूचक की सराहना करता हूं जो मुझे इस रंग के मुद्दे को ठीक करने में मदद कर सकता है।

उत्तर

13

आप सही हैं, ओपनसीवी का डिफ़ॉल्ट पिक्सेल प्रारूप बीजीआर है।

ffmpeg पक्ष पर समकक्ष प्रारूप बीजीआर 24 होगा, इसलिए यदि आप नहीं चाहते हैं तो आपको इसे YUV420p में परिवर्तित करने की आवश्यकता नहीं है।

This post दिखाता है कि कैसे stdout को वेब कैमरा से तख्ते पर कब्जा और फ्रेम लिखने के लिए एक अजगर आवेदन का उपयोग करने के लिए। इसका उद्देश्य सीएमडी-लाइन पर इस ऐप को आमंत्रित करना है और परिणाम को सीधे ffmpeg एप्लिकेशन पर पाइप करना है, जो डिस्क पर फ्रेम स्टोर करता है। वास्तव में काफी चालाक!

capture.py:

import cv, sys 

cap = cv.CaptureFromCAM(0) 
if not cap: 
    sys.stdout.write("failed CaptureFromCAM") 

while True : 
    if not cv.GrabFrame(cap) : 
     break 

    frame = cv.RetrieveFrame(cap) 
    sys.stdout.write(frame.tostring()) 

और कमांड खोल पर निष्पादित किया जाना है:

python capture.py | ffmpeg -f rawvideo -pix_fmt bgr24 -s 640x480 -r 30 -i - -an -f avi -r 30 foo.avi 

कहाँ:

  • -r देता है वो फ्रेम कैमरा
  • -एक कहते हैं से आ रही दर "ऑडियो सांकेतिक शब्दों में बदलना नहीं है"

मैं OpenCV 2.4.2 के साथ अपने मैक ओएस एक्स पर इस समाधान का परीक्षण किया।

संपादित करें:

मामले में आप कैमरे से रिकॉर्ड करने के लिए प्रयास नहीं किया है और OpenCV का उपयोग डिस्क पर एक mp4 फ़ाइल करने के लिए वीडियो लिखने के लिए, यहाँ हम चले:

import cv, sys 

cap = cv.CaptureFromCAM(0) # 0 is for /dev/video0 
if not cap: 
    sys.stdout.write("!!! Failed CaptureFromCAM") 
    sys.exit(1) 

frame = cv.RetrieveFrame(cap) 
if not frame: 
    sys.stdout.write("!!! Failed to retrieve first frame") 
    sys.exit(1) 

# Unfortunately, the following instruction returns 0 
#fps = cv.GetCaptureProperty(cap, cv.CV_CAP_PROP_FPS) 
fps = 25.0  # so we need to hardcode the FPS 
print "Recording at: ", fps, " fps" 

frame_size = cv.GetSize(frame) 
print "Video size: ", frame_size 

writer = cv.CreateVideoWriter("out.mp4", cv.CV_FOURCC('F', 'M', 'P', '4'), fps, frame_size, True) 
if not writer: 
    sys.stdout.write("!!! Error in creating video writer") 
    sys.exit(1) 


while True : 
    if not cv.GrabFrame(cap) : 
     break 
    frame = cv.RetrieveFrame(cap) 
    cv.WriteFrame(writer, frame) 

cv.ReleaseVideoWriter(writer) 
cv.ReleaseCapture(cap) 

मैंने मैक ओएस एक्स और ओपनसीवी 2.4.2 पर पायथन 2.7 के साथ इसका परीक्षण किया है।

+0

आपके उत्तर के लिए धन्यवाद। मेरे पास अभी तक समाधान की जांच करने का समय नहीं था लेकिन यह दिलचस्प लग रहा है। मैंने पहले ही bgr24 pix_fmt का उपयोग करने का प्रयास किया है लेकिन यह libx264 कोडेक के साथ काम नहीं करता है। मुझे यकीन नहीं है कि मुझे वास्तव में libx264 का उपयोग करने की आवश्यकता है। मुझे एक क्रॉस-प्लेटफ़ॉर्म समाधान (विंडोज़, मैक, लिनक्स) की आवश्यकता है और इसके परिणामस्वरूप libx264 की आवश्यकता हो सकती है। मुझे जांच करने की ज़रूरत है। – luc

+0

विंडोज libx264 पर डिफ़ॉल्ट कोडेक है और छवि को गलत रंग होने का कारण बनता है क्योंकि यह bgr24 pix_fmt – luc

+0

के साथ संगत नहीं है पूछने के लिए खेद है, लेकिन आप वीडियो फ़ाइल बनाने के लिए ओपनसीवी का उपयोग क्यों नहीं करते? – karlphillip

0

में अपलोड किए गए रूपांतरण सूत्रों की जांच की गई: http://en.wikipedia.org/wiki/YCbCr?

+0

लिंक के लिए धन्यवाद लेकिन मैं इन सभी सूत्रों के बीच थोड़ा सा खो गया हूं। इसे लागू करने के लिए आप क्या सलाह देंगे? – luc

1

क्या आपनेऔर merge का उपयोग कर ओपनसीवी में सीबी/सीआर चैनलों को स्विच करने का प्रयास किया है?

+0

मैंने अलग-अलग रूपांतरणों की कोशिश की। तुम किसकी सिफारिश करना चाहोगे? – luc

+0

मेरा सुझाव है कि आप केवल सीबी और सीआर चैनलों को स्वैप करें। वाईसीबीसीआर में, वाई "ल्यूमिनेंस" भाग के लिए खड़ा है, जो भूरे रंग के स्तर से कम या कम है। रंग की जानकारी 2 "क्रोमिनेंस" चैनलों में संग्रहित की जाती है, सीआर (क्रोमिनेंस रेड में) और सीबी (क्रोमिनेंस ब्लू)। जैसा कि आपने कहा था, ओपनसीवी वाईसीआरसीबी में परिवर्तित होता है, और एफएमपीपीजी वाईयूवी = वाईसीबीसीआर। यह + तथ्य यह है कि आपकी छवियां नीली दिखाई देती हैं, मुझे लगता है कि आप आसानी से क्रोमिनेंस चैनलों को स्वैप कर सकते हैं, सीआर <-> सीबी। – remi

+0

धन्यवाद। इससे समाधान खोजने में मदद मिली। मैंने स्प्लिट और मर्ज का उपयोग करके एक कनवर्टर बनाया है और मुझे एहसास हुआ कि मेरे पास एक डबल-रूपांतरण था और एक प्रतिलिपि का उपयोग करना पर्याप्त था :) – luc

0

libx264 कोडेक बीजीआर छवियों को संसाधित करने में सक्षम है। वाईसीबीसीआर में किसी भी रूपांतरण का उपयोग करने की आवश्यकता नहीं है। Ffmpeg को एक स्पेसिफिक pix_ftm देने की आवश्यकता नहीं है। मैं आरजीबी का उपयोग कर रहा था और यह वीडियो पर नीली प्रभाव का कारण बन रहा था।

समाधान बिना किसी रूपांतरण के कैमरे द्वारा छोड़ी गई मूल छवि का उपयोग करना था। :)

मैंने अपनी पिछली जांच में यह कोशिश की और यह ऐप को दुर्घटनाग्रस्त कर रहा था। समाधान कैमरा द्वारा लौटा फ्रेम कॉपी करने के लिए है।

frame = opencv.QueryFrame(camera) 
    if not frame: 
     return None, None 

    # RGB : use this one for displaying on the screen 
    im_rgb = opencv.CreateImage(self.size, opencv.IPL_DEPTH_8U, 3) 
    opencv.CvtColor(frame, im_rgb, opencv.CV_BGR2RGB) 

    # BGR : Use this one for the video 
    im_bgr = opencv.CreateImage(self.size, opencv.IPL_DEPTH_8U, 3) 
    opencv.Copy(frame, im_bgr) 

    return im_rgb, im_bgr