OpenCV中圖像顯示你不知道的編程技巧
- 2019 年 10 月 6 日
- 筆記
寫代碼我們是認真的! 閱讀本文大概需要 4min
OpenCV 中最常用的一個API函數 imshow 各種編程與應用技巧,是否有你以前一直想的,但是從來沒有成功過的操作!
最簡單的顯示方式
01
很多人學習OpenCV,學會前面兩個函數就是
Imread – 讀圖像 Imshow – 顯示圖像
代碼看起來是這樣
Mat src = imread("D:/images/test.png"); imshow("input", src);
覺得好簡單,真的好簡單,但是他們遇到大圖的時候,就會發現OpenCV無法完整顯示!想把多張圖像,顯示在一個窗口裏面,無法做到!顯示浮點數圖像全白!這些問題其實是你不了解如何正確使用imshow導致,下面就分享一下本人的做法,也許你會有更好的,歡迎留言拍磚!
浮點數圖像顯示的正確姿勢
02

上面的圖像,左側是輸入圖像,中間與右側都是浮點數圖像的顯示結果。中間圖像對應的代碼如下:
Mat m1; src.convertTo(m1, CV_32F); imshow("m1", m1);
顯示的結果是全白色,沒有任何可見的信息,難道是程序錯拉,程序沒有錯誤,Mat類型轉換從讀入圖像的CV_8UC3轉為CV_32FC3也沒有錯誤。修改一下代碼
Mat m2; src.convertTo(m2, CV_32F, 0.00392); imshow("m2", m2);
只是在類型轉換的時候多加了一個參數,這個參數是什麼 1/255 = 0.00392
意思是把像素值從0~255 轉換為0~1之間的浮點數,然後再顯示,顯示結果對應上圖最右側。
解釋:原來imshow顯示浮點數的時候,只支持0~1之間的浮點數顯示,超過1就認為是白色,所以在沒有對值域做rescale的時候,中間的浮點數Mat顯示只能是白色。
如何在一個Mat對象中顯示多張圖
03
這個是很多人問我過的問題,其實很簡單,創建一個空白的Mat,把兩張圖的內容放進去,然後顯示新創建的Mat對象就可以把兩張圖顯示在一個窗口裏面。先看效果

代碼實現如下:
Mat src1 = imread("D:/images/lena.png"); Mat src2 = imread("D:/images/t3.jpg"); imshow("src1", src1); imshow("src2", src2); // 構建新圖像的大小 int width = src1.cols + src2.cols; int height = max(src1.rows, src2.rows); Mat two = Mat::zeros(Size(width, height), src1.type()); // 構建ROI Rect r1(0, 0, src1.cols, src1.rows); Rect r2(0, 0, src2.cols, src2.rows); r2.x = src1.cols; // 內容copy src1.copyTo(two(r1)); src2.copyTo(two(r2)); imshow("two images demo", two); waitKey(0);
上述代碼,基本上已經很通用,直接讀入任意兩張圖像都可以,唯一需要注意的是合併之後圖像太大無法顯示怎麼辦,沒關係,我們這就來搞定這個問題。
圖像太大,無法完整顯示怎麼辦
04
這個問題,其實不能怪imshow,主要原因出在opencv的默認窗口創建上面,在OpenCV中你可以直接調用imshow函數去顯示圖像,默認會創建一個同名的窗口,這個窗口的默認打開模式是WINDOW_AUTOSIZE, 這種情況下你是無法調整窗口大小的,很多人其實是掉到這個坑裏面去的,解決辦法就是代碼顯式創建一個可以調整大小的窗口,一行代碼搞定:
namedWindow("input", WINDOW_FREERATIO)
然後調用
imshow("input", yourMat)
顯示時候,注意保持窗口名稱一致即可,再大的圖像顯示都沒有問題,前提是內存真的夠大!
千萬不要嘗試的Mat類型圖像顯示
Imshow其實只支持 CV_8U與CV_32F 類型的數據顯示,其它Mat類型數據最好先轉換為這兩種類型之一再顯示,不然你可能會得到各種錯誤,各種掉坑。建議不要嘗試跟API對着干,倒霉的只會是你自己。
收藏此帖,從此圖像顯示不會再有問題