如何在OpenCV中從YUV文件讀取幀?如何在OpenCV中從YUV文件讀取幀?
回答
我不認爲這是可能的,至少在目前的版本。當然,這樣做並不難,但它不是那麼有趣的功能,因爲:
- OpenCV通常適用於RGB格式的網絡攝像頭流或編碼文件,它們是直接解碼爲RGB以用於顯示目的;
- OpenCV致力於計算機視覺,其中YUV是一種比在編碼社區中不太常見的格式;
- 有很多不同的YUV格式,這意味着很多工作來實現它們。
儘管使用cvCvtColor()
,轉換仍然是可能的,這意味着它仍然有一些利益。
UPDATE這裏有代碼的一個新版本:https://github.com/chelyaev/opencv-yuv
我張貼一些代碼,會讀一個單一 YUV 4:2:0平面圖像文件。您可以直接將其應用於大多數YUV文件(只需繼續讀取相同的FILE
對象)。 例外這是當處理YUV files that have a header(通常,他們有一個*.y4m
擴展名)。如果要對付這樣的文件,你有兩個選擇:
- 寫自己的函數使用下面的代碼
- 剝去* .y4m圖像頭之前消耗從
FILE
對象的報頭數據(使用ffmpeg
或類似的工具)。這是我喜歡的選項,因爲它是最簡單的。
它也不適用於任何其他形式的YUV格式(非平面,不同的色度抽取)。正如@Stephane指出的,有很多這樣的格式(其中大多數沒有任何標識頭),這可能是OpenCV不支持它們的原因。
但與他們的合作是相當簡單:
- 開始用圖像和它的尺寸
- 讀取亮度和色度分爲3個獨立的圖像
- 高檔(該讀YUV文件時需要)色度圖像減少2倍以補償色度抽取。 注意,實際上有幾個方法來補償色度抽取。上採樣只是最簡單的
- 組合成YUV圖像。如果你想RGB,你可以使用
cvCvtColor
。
最後,代碼:
IplImage *
cvLoadImageYUV(FILE *fin, int w, int h)
{
assert(fin);
IplImage *py = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
IplImage *pu = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);
IplImage *pv = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);
IplImage *pu_big = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
IplImage *pv_big = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
IplImage *image = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3);
IplImage *result = NULL;
assert(py);
assert(pu);
assert(pv);
assert(pu_big);
assert(pv_big);
assert(image);
for (int i = 0; i < w*h; ++i)
{
int j = fgetc(fin);
if (j < 0)
goto cleanup;
py->imageData[i] = (unsigned char) j;
}
for (int i = 0; i < w*h/4; ++i)
{
int j = fgetc(fin);
if (j < 0)
goto cleanup;
pu->imageData[i] = (unsigned char) j;
}
for (int i = 0; i < w*h/4; ++i)
{
int j = fgetc(fin);
if (j < 0)
goto cleanup;
pv->imageData[i] = (unsigned char) j;
}
cvResize(pu, pu_big, CV_INTER_NN);
cvResize(pv, pv_big, CV_INTER_NN);
cvMerge(py, pu_big, pv_big, NULL, image);
result = image;
cleanup:
cvReleaseImage(&pu);
cvReleaseImage(&pv);
cvReleaseImage(&py);
cvReleaseImage(&pu_big);
cvReleaseImage(&pv_big);
if (result == NULL)
cvReleaseImage(&image);
return result;
}
我遇到同樣的問題。我的解決方案是 1。讀取一個yuv幀(如I420)到一個字符串對象「yuv」。 2.將yuv幀轉換爲BGR24格式。我使用libyuv來做到這一點。爲libyuv函數編寫python包裝很容易。現在你得到另一個BGR24格式的字符串對象「bgr」。 3.使用numpy.fromstring從「bgr」字符串對象中獲取圖像對象。您需要更改圖像對象的形狀。
下面是一個簡單的yuv查看器供您參考。
import cv2
# below is the extension wrapper for libyuv
import yuvtorgb
import numpy as np
f = open('i420_cif.yuv', 'rb')
w = 352
h = 288
size = 352*288*3/2
while True:
try:
yuv = f.read(size)
except:
break
if len(yuv) != size:
f.seek(0, 0)
continue
bgr = yuvtorgb.i420_to_bgr24(yuv, w, h)
img = np.fromstring(bgr, dtype=np.uint8)
img.shape = h,w,3
cv2.imshow('img', img)
if cv2.waitKey(50) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
如前所述,有許多類型的YUV格式:
要從OpenCV的YUV格式轉換爲RGB格式很簡單:
- 創建一個用於該幀數據的適當尺寸的三維OpenCV Mat
- 用所需的d爲RGB數據創建一個空Mat imension並用3個信道
- 最後使用cvtColor於兩個墊之間進行轉換,使用正確的轉換標誌枚舉
這裏是一個例子用於YUV緩衝在YV12格式:
Mat mYUV(height + height/2, width, CV_8UC1, (void*) frameData);
Mat mRGB(height, width, CV_8UC3);
cvtColor(mYUV, mRGB, CV_YUV2RGB_YV12, 3);
關鍵技巧是在您轉換之前定義您的RGB墊的尺寸。
這是正確答案。 我正在處理YUV的NV12變化,這些幫助我瞭解了格式: https://wiki.videolan.org/YUV/#NV12,https://commons.wikimedia.org/wiki/File:Common_chroma_subsampling_ratios .SVG – rhardih 2016-10-11 13:05:05
我寫了一個非常簡單的python代碼來讀取二進制文件中的YUV NV21流。
import cv2
import numpy as np
class VideoCaptureYUV:
def __init__(self, filename, size):
self.height, self.width = size
self.frame_len = self.width * self.height * 3/2
self.f = open(filename, 'rb')
self.shape = (int(self.height*1.5), self.width)
def read_raw(self):
try:
raw = self.f.read(self.frame_len)
yuv = np.frombuffer(raw, dtype=np.uint8)
yuv = yuv.reshape(self.shape)
except Exception as e:
print str(e)
return False, None
return True, yuv
def read(self):
ret, yuv = self.read_raw()
if not ret:
return ret, yuv
bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_NV21)
return ret, bgr
if __name__ == "__main__":
#filename = "data/20171214180916RGB.yuv"
filename = "data/20171214180916IR.yuv"
size = (480, 640)
cap = VideoCaptureYUV(filename, size)
while 1:
ret, frame = cap.read()
if ret:
cv2.imshow("frame", frame)
cv2.waitKey(30)
else:
break
- 1. 在opencv中讀取YUV文件
- 2. 如何從YUV文件中提取幀?
- 3. 我如何從給定的yuv 4:2:0文件中提取yuv幀
- 4. 如何在OpenCV中逐幀讀取視頻文件?
- 5. 無法將YUV幀從ffmpeg寫入.yuv文件
- 6. 如何從MPEG2 TS文件中提取原始YUV文件?
- 7. 如何YUV幀(從OTVideoFrame)轉換爲CVPixelBuffer
- 8. 如何從Android中的電影文件中讀取每個幀?
- 9. 如何OpenCV的C++讀取.xml文件
- 10. Gstreamer自定義插件從文件讀取數據(YUV)?
- 11. 如何從Android中的文件讀取OpenCV Mat對象?
- 12. 在OpenCV中讀取YAML文件
- 13. 如何在matlab中讀取y4m視頻(獲取幀)文件
- 14. 從文件夾(OpenCV)讀取圖像
- 15. 如何在OpenCV中讀取Android中的AVI文件
- 16. 如何從視頻MATLAB中讀取幀?
- 17. YUV幀到CGContext
- 18. OpenCV Python - 讀取pgm文件
- 19. 如何在OpenCv中讀取不同格式的XML文件?
- 20. 從視頻文件中抓取幀的最快方法OpenCV
- 21. 如何處理yuv文件
- 22. 如何從csv文件讀取數據幀時設置列?
- 23. 從OpenCV中的VideoCapture讀取每第n幀
- 24. 無法讀取OpenCV中的AVI文件
- 25. OpenCV掛在讀取(),抓取()等從文件
- 26. Android中的YUV幀縮放
- 27. 如何給YUV數據輸入到Opencv?
- 28. 如何從文件中讀取,然後繼續從cin讀取?
- 29. 如何獲得YUV幀的分辨率
- 30. 如何將YUV幀轉換爲視頻?
我現在有同樣的問題,我試圖打開並使用具有UYVY視頻工作(4:2:2)編解碼器,我想你的代碼,但它沒有工作,我知道,你在回答中提到過,但你能否說出原因?在此先感謝您的幫助 – Engine 2013-02-13 10:09:08
我發佈的代碼處理YUV 4:2:0。由於您的視頻採用YUV 4:2:2格式,因此我的代碼無法直接在您的視頻上播放。您需要修改代碼來處理您的格式。有關更多詳細信息,請參閱:http://en.wikipedia.org/wiki/Chroma_subsampling#4:2:2 – misha 2013-02-14 04:21:46