2016-12-01 53 views
-1

這不是一個最頭痛的分析有問題的,因爲這樣做下面也將導致連接錯誤雖然沒有歧義:Convert命令行參數的QImage

QImage baseline("C:\img1.png"); 
QImage test_image("C:\img1.png"); 

我的申請得到2命令行參數是通向2個不同圖像的路徑。

我想將它們轉換爲QImage後我可以使用Qt提供的==運算符進行比較。

我曾嘗試以下方法去,但我每次收到鏈接的問題:

嘗試1:

QImage baseline(argv[1]); 
    QImage test_image(argv[2]); 

嘗試2(轉換爲QString的在前):

QString base_path = QString::fromStdString(argv[1]); 
    QString test_path = QString::fromStdString(argv[2]); 
    QDir baseline(base_path); 
    QDir test_image(test_path); 

我不認爲這與沒有包含正確的庫有關,因爲如果我只是做以下操作,程序編譯並鏈接正常:

Qimage test_image(); 

已經看到下面的線程,不幸的是它是不是在我的情況非常有幫助: Constructing QImage from unsigned char* data

任何思考什麼可能會造成鏈接錯誤?我懷疑他們會是非常有益的,但我會離開這裏的鏈接程序錯誤消息:

Severity Code Description Project File Line Suppression State Error LNK2019 unresolved external symbol "__declspec(dllimport) public: __thiscall QString::~QString(void)" ([email protected]@[email protected]) referenced in function _main image_compare_executable c:\Users\gela8178\documents\visual studio 2015\Projects\image_compare_executable\image_compare_executable\image_compare_executable.obj 

1 Error LNK2019 unresolved external symbol "__declspec(dllimport) public: static class QString __cdecl QString::fromStdString(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" ([email protected]@@[email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z) referenced in function _main image_compare_executable c:\Users\gela8178\documents\visual studio 2015\Projects\image_compare_executable\image_compare_executable\image_compare_executable.obj 

1 Error LNK1120 2 unresolved externals image_compare_executable c:\users\gela8178\documents\visual studio 2015\Projects\image_compare_executable\Debug\image_compare_executable.exe 1 

包括我的代碼中的相關片段導致連接問題:

#include "stdafx.h" 
#include <iostream> 
#include <opencv2/opencv.hpp> 
#include <QtGui/QtGui> 

using namespace cv; 

int main(int argc, char* argv[]) 
{ 
// Check the number of parameters 
if (argc < 3) { 
    std::cerr << "Error: " << argv[0] << " : " << "Missing arguments" << std::endl; 
    return 1; 
} 
std::cout << "Baseline: " << argv[1] << "\n" << "Test Image: " << argv[2] << std::endl; 

QImage baseline(QString(argv[1])); 
QImage test_image(QString(argv[2])); 

if (baseline == test_image) 
{ 
    std::cout << "Algorithm: Mem Compare" << "\n" << "Result: = Pass" << std::endl; 
} 
else 
{ 
    std::cout << "Algorithm: Mem Compare" << "\n" << "Result: = Fail" << std::endl; 
} 
std::cout << "--------------------------------------------------------" << std::endl; 

// ***************************************************************************** // 

//Run MSSIM and output tuple 
Mat i1 = imread(argv[1]); 
Mat i2 = imread(argv[2]); 

Scalar min_ssim = getMSSIM(i1, i2); 
double R = min_ssim[0]; 
double G = min_ssim[1]; 
double B = min_ssim[2]; 

std::cout << "Algorithm: MSSIM" << "\n" << "Result: " << "(" << R << ", " << G << ", " << B << ")" << std::endl; 

std::cout << "--------------------------------------------------------" << std::endl; 

return 0; 
} 

SOLUTION:

望着QImage的構造here,需要一個QString的將其作爲一個const reference的唯一實例:

QImage(const QString &fileName, const char *format = Q_NULLPTR) 

做以下

QImage baseline(QString(argv[1])); 

被扔鏈接錯誤,因爲QString的是用R引用傳遞,通過時間的QImage試圖訪問它遭到破壞。因此,可能的解決方法是要麼單獨做的QString的分配,並把它傳遞到QImage的這樣只是做:

QImage baseline(argv[1]); 
QImage test_image(argv[2]); 
+0

'argv'不是std :: string的集合。它是一個零終止的C風格字符串數組。嘗試類似'QImage baseline(QString(argv [1]));'但是我懷疑你的比較嘗試是有成效的。圖像格式化會得到一個確切的比較 – infixed

+0

@infixed謝謝。您的建議確實解決了鏈接器錯誤。你能解釋一下圖像格式化的含義嗎?我正在尋找一個像素比較的簡單像素,這就是==我們所理解的==操作符。但是現在當我做'if(baseline == test_image)'時,我得到了更多的鏈接器錯誤。 – Gela

+0

因爲圖像文件看起來與我們的眼睛相同並不意味着它們的二進制表示在內存中是相同的。然而'=='會做一個二進制的比較比較。例如,考慮具有不同質量設置的兩個JPEG文件。 JPEG壓縮算法會將不同的像素組合在一起,因此當您比較二進制文件時,它們將會不同。實際上,它就好像您只是逐字節比較實際文件字節序列以查看它們是否匹配。解碼他們到一個QImage可能適用於BMP或PNG文件,但我不會希望你的新鏈接錯誤太多 – infixed

回答

0

首先,QImage baseline(QString(argv[1]))是最讓人頭疼的解析。期。你正在使用一個不會提醒你的編譯器。 (argv[1])附近的括號是多餘的。該聲明的規範形式如下:

QImage baseline(QString [1]); 

您也不應該使用argv,因爲它不可移植。例如,在Windows上,argv是垃圾。

使用QCoreApplication::arguments()代替:

int main(int argc, char ** argv) { 
    QGuiApplication app{argc, argv}; 
    auto const args = app.arguments(); 
    if (args.count() < 3) 
    return 1; 
    QImage baseline(args[1]); 
    QImage test_image(args[2]); 
    //... 
} 

假如你從一開始就用它,你甚至不會碰到你有問題。所以你可以看到它的好處是雙重的:它可以保護你免受最令人頭痛的解析,它工作正常的Windows :)

當然,你也可以使用QApplication如果你有一個基於插件的UI 。但對於QImage,您只需要QGuiApplication

常見Qt方法/構造函數(如__declspec(dllimport) public: __thiscall QString::~QString(void))的鏈接器錯誤表明您沒有將項目鏈接到Qt。

如果您已經在使用qmake,那麼只有在您未將gui模塊添加到項目中時才需要#include <QtGui/QtGui>。正確的形式是#include <QtGui>。如果編譯器抱怨它找不到該文件,那麼您沒有將您的項目設置爲正確使用Qt。一旦你這樣做,文件應該編譯和鏈接 - 再次假設你使用qmake或cmake和Qt宏。

+0

謝謝,但這並沒有解決鏈接器問題。我剛剛發佈了我的整個代碼(不包括'getMSSIM'的實際實現),你可以看看這個,並告訴我你是否能看到我做錯了什麼? – Gela

+0

您可能正在使用不兼容的編譯器。請記住,給定的Qt版本只與一個特定的編譯器系列兼容。例如。如果你有使用MSVC 2013構建的Qt,那麼它就沒有機會與任何其他版本的MSVC或任何其他編譯器(例如gcc或clang)一起工作。你也沒有談論你如何建立你的項目。你正在使用'qmake + jom/nmake',還是其他的? –

+0

我不認爲這是一個編譯器兼容性問題,因爲我在不同的項目中使用相同的設置沒有任何問題。我使用Visual Studio 2015年,在那裏我打電話'如果(基線== test_image)' – Gela