Opencv關於imread和imwrite研習-Qt開啟影象判斷影象型別
今天要寫一個判斷是否為二值圖,灰度圖,彩色圖的程式,本來邏輯沒問題,但是Qt按鈕始終在彩色圖
於是單獨讀入圖片,除錯程式,發現,二值圖和灰度圖都是三通道,百思不得解,原來
我使用的opencv imread預設讀取三通道彩色圖
讀影象的時候imread()函式的第二個引數使用的是預設值,那麼這個時候都是以color形式讀取的,所有就又變回3通道了;下面是第二個引數的介紹
flags – Flags specifying the color type of a loaded image: – CV_LOAD_IMAGE_ANYDEPTH - If set, return 16-bit/32-bit image when the input hasthe corresponding depth, otherwise convert it to 8-bit. – CV_LOAD_IMAGE_COLOR - If set, always convert image to the color one – CV_LOAD_IMAGE_GRAYSCALE - If set, always convert image to the grayscale one
程式碼如下:
然後重新測試,發現依然總是選中那一個按鈕,找錯,發現,我的影象有問題,灰度圖和二值圖竟然是三通道,尋找問題,發現,我的影象為了測試方便,直接在opencv中變換後使用imwrite儲存,但是imwrite儲存會出現上述問題,尋找資料,發現
參考部落格:
比如我有如下的一個233M的圖片
經過下面的程式讀進記憶體,再次儲存後,圖片容量就急劇變小了!
#include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using namespace std; using namespace cv; int main(int argc, char** argv) { Mat img = imread("src1.jpg"); imwrite("test.jpg", img); return 0; }
儲存後的圖片,只剩下126M了!怎麼回事!我什麼都沒做啊,圖片大小怎麼就大大縮水了呢?
通過翻閱一些資料才知道,原來是圖片格式惹得禍。其實有些圖片格式是自帶壓縮的,比如jpg格式,而bmp格式的圖片是不帶任何壓縮,這就是每種圖片的特點,如果對這些知識點不清楚的話,很容易踩坑!平時我們操作的影象大小大多數都以KB為單位,所以經過一番“隱形壓縮”後我們很難發現圖片大小變小了,但是,當我們操作大圖的時候,這種壓縮效果一下子就看出來了。
那麼如果我們在使用imwrite儲存圖片時想提高儲存圖片的質量,該如何操作?
要改變儲存的圖片的質量,關鍵在於imwrite函式的第三個引數。
先看imwrite的宣告
CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>());
第三個引數說明:const std::vector
•對於JPEG格式的圖片,這個引數表示從0-100的圖片質量(CV_IMWRITE_JPEG_QUALITY),預設值是95.
•對於PNG格式的圖片,這個引數表示壓縮級別(CV_IMWRITE_PNG_COMPRESSION)從0-9.較高的值意味著更小的尺寸和更長的壓縮時間而預設值是3.
•對於PPM,PGM或PBM格式的圖片,這個引數表示一個二進位制格式標誌(CV_IMWRITE_PXM_BINARY),取值為0或1,而預設值為1.
調整jpg影象格式的儲存質量
opencv的imwrite預設儲存的jpg圖片質量為95,如果想進一步提高儲存圖片的質量,可以這麼寫
程式碼如下
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat img = imread("src1.jpg");
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY); //選擇jpeg
compression_params.push_back(100); //在這個填入你要的圖片質量
imwrite("test2.jpg", img, compression_params);
return 0;
}
可以看出,經過引數調整後,jpg格式儲存的圖片的大小有了很大的提升。
但是無論如何,以jpg格式儲存圖片還是不能百分百儲存原影象的!
但是即使我們把圖片質量寫成100,圖片質量跟原圖還是右一定壓縮的,比如原圖233M,讀入再儲存為jpg格式容量就變為229M。
那當我們不斷讀入圖片,又不斷儲存圖片為jpg格式,圖片的質量就會不斷降低!
所以有以下總結:
第一,opencv的儲存圖片函式imwrite是可以通過第三個函式引數來調整儲存圖片的壓縮比的,比如儲存圖片為jpg格式,我們如果我們寫成
第二,jpg格式的圖片讀進記憶體,如果再儲存為jpg格式後,容量會被壓縮的,這是jpg格式的特性,怎麼調整壓縮比都避免不了失真(損失圖片質量)。
此時,二值圖的儲存和灰度圖的儲存就沒問題了
這裡我選擇的是jepg即jpg,如果你要選擇其他格式儲存,記得更改格式
enum
{
CV_IMWRITE_JPEG_QUALITY =1,
CV_IMWRITE_JPEG_PROGRESSIVE =2,
CV_IMWRITE_JPEG_OPTIMIZE =3,
CV_IMWRITE_JPEG_RST_INTERVAL =4,
CV_IMWRITE_JPEG_LUMA_QUALITY =5,
CV_IMWRITE_JPEG_CHROMA_QUALITY =6,
CV_IMWRITE_PNG_COMPRESSION =16,
CV_IMWRITE_PNG_STRATEGY =17,
CV_IMWRITE_PNG_BILEVEL =18,
CV_IMWRITE_PNG_STRATEGY_DEFAULT =0,
CV_IMWRITE_PNG_STRATEGY_FILTERED =1,
CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY =2,
CV_IMWRITE_PNG_STRATEGY_RLE =3,
CV_IMWRITE_PNG_STRATEGY_FIXED =4,
CV_IMWRITE_PXM_BINARY =32,
CV_IMWRITE_WEBP_QUALITY =64,
CV_IMWRITE_PAM_TUPLETYPE = 128,
CV_IMWRITE_PAM_FORMAT_NULL = 0,
CV_IMWRITE_PAM_FORMAT_BLACKANDWHITE = 1,
CV_IMWRITE_PAM_FORMAT_GRAYSCALE = 2,
CV_IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA = 3,
CV_IMWRITE_PAM_FORMAT_RGB = 4,
CV_IMWRITE_PAM_FORMAT_RGB_ALPHA = 5,
};
還有一點錯誤,開啟二值圖的時候,會跳到灰度圖,我的判斷是隻有
255和0,但是我用的是大津法求閾值,好像不是隻有255和0,偶爾還有1,254,之類的,查看了下閾值函式
/** Threshold types */
enum
{
CV_THRESH_BINARY =0, /**< value = value > threshold ? max_value : 0 */
CV_THRESH_BINARY_INV =1, /**< value = value > threshold ? 0 : max_value */
CV_THRESH_TRUNC =2, /**< value = value > threshold ? threshold : value */
CV_THRESH_TOZERO =3, /**< value = value > threshold ? value : 0 */
CV_THRESH_TOZERO_INV =4, /**< value = value > threshold ? 0 : value */
CV_THRESH_MASK =7,
CV_THRESH_OTSU =8, /**< use Otsu algorithm to choose the optimal threshold value;
combine the flag with one of the above CV_THRESH_* values */
CV_THRESH_TRIANGLE =16 /**< use Triangle algorithm to choose the optimal threshold value;
combine the flag with one of the above CV_THRESH_* values, but not
with CV_THRESH_OTSU */
};
如果使用了大津法之類的,需要其他方法判斷,但是使用別的方法,需要自己判斷閾值
糾結
最後我向現實屈服,先草率解決問題,有時間看原始碼,看看為啥會有1和254等接近最大值最小值的數
最後附上,判斷彩色圖二值圖灰度圖的程式
if (text.channels() == 3){
int a = 3;
}
else if (text.channels() == 1)
{
int rowNumber = text.rows; //獲取影象矩陣行數
int colNumber = text.cols; //三通道影象每行元素個數為列數x通道數
int pixelCount = 0;
for (int i = 0; i < rowNumber; i++)
{
uchar* pixelPtr = text.ptr<uchar>(i); //獲取矩陣每行首地址指標
for (int j = 0; j < colNumber; j++)
{
if (pixelPtr[j] != 0 && pixelPtr[j] != 255)
{
pixelCount++;
}
}
}
if (pixelCount == 0) //二值圖
{
int c = 3;
}
else{
int b = 3; //灰度圖
}
}
}