今天調個程序,源代碼輸入是PGM格式的灰度圖,方便起見,我直接用matlab批量轉的文件。然而,在程序中使用imread(filename, IMREAD_GRAYSCALE)時,驚奇發現,同一種圖片的兩種輸入,卻得到了不同的結果,儘管結果類似。我驚了!!彩色轉灰度這玩意還有不一樣的事,這個事坑了我好幾天,今天終於明白了,現在我把問題及解決方案整理如下。
問題引出
一張jpg彩色圖片file.jpg,一張由matlab - imread - rgb2gray得到相應的灰度pgm圖file.pgm。則由如下代碼得到的灰度圖imgG1和imgG2,值不完全一致。
cv::Mat imgG1 = cv::imread("file.pgm", 0);
cv::Mat imgG2 = cv::imread("file.jpg", 0);
問題分析
從一開始,我以爲是我程序問題,找了好久無頭緒,換了另一種計算灰度的代碼(如下),驚奇發現,得到的灰度與pgm對應數據一致。
cv::Mat imgC2 = cv::imread("file.jpg");
cv::Mat imgG2;
cv::cvtColor(imgC2, imgG2, CV_BGR2GRAY);
這讓我不禁陷入了人生與科研的大思考,我從6點搜百度搜到第二天1點,沒有得到任何有用信息。只能去GG搜下,結果發現有人跟我遇到了一樣的問題,只不過他是計算直方圖。但是似乎這些相關連接沒給出明確的方法。
最後,找到一個網址,上面說了這個問題的原因Grayscale conversion algorithm of OpenCV’s imread(),我翻譯如下。
在opencv3.0中,
cv::IMREAD_COLOR
解析jpg時候,由cv::JpegDecoder
解碼得到一個RGB圖像,然後由icvCvt_RGB2BGR_8u_C3R()
函數交換R和B空間,得到BGR格式的彩色圖。cv::IMREAD_GRAYSCALE
這個圖像由cv::JpegDecoder
解碼得到一個灰度圖,所有的顏色轉換和其他預處理或後處理等相關細節都是由libjpeg處理的,最後,將解壓縮的數據複製到給定cv::Mat
的內部緩衝區中。因此,在cv::IMREAD_GRAYSCALE
中沒有調用opencv中的函數cv::cvtColor
來進行顏色轉換。
解決方案
爲了保證與matlab生成數據保持一致,我們按照如下代碼來獲得灰度圖。切記,以後不要再指定imread的第二個參數爲0來獲得灰度圖了。
cv::Mat imgC2 = cv::imread("file.jpg");
cv::Mat imgG2;
cv::cvtColor(imgC2, imgG2, CV_BGR2GRAY);
後話,好多問題我都是從github的issue和stackoverflow.com搜到的,如果百度不爬這兩個網站。
藥丸つ﹏⊂。
終於可以無憂無慮睡覺了(~﹃~)~zZ