Siv3Dとopencvの併用について
keni 2016/09/21(Wed) 08:14
Siv3D(August2016v2) を選択してプロジェクトを作成した際に、
opencvの機能を使用しようとするとビルド時にエラーが出てしまいます。
Siv3D(August2016v2) を選択してプロジェクトを作成した場合、
imshowなどのウィンドウを生成してしまうようなコードは使用できないのでしょうか?
それとも、何か別の問題があるのでしょうか?
下記にエラーとソースコードを記載致します。
【エラー】
エラー:LNK2019 未解決の外部シンボル "void __cdecl Main(void)" (?Main@@YAXXZ) が関数 "unsigned int __stdcall MainThread(void *)" (?MainThread@@YGIPAX@Z) で参照されました。
ファイル:Siv3D_d.lib(Siv3DMain.obj)
エラー:LNK1120 1 件の未解決の外部参照 SimplePrototypeSystem
ファイル:SimplePrototypeSystem.exe
【ソースコード】
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <vector>
#include<random>
#include<string>
#include<strstream>
#include <Siv3D.hpp>
int main()
{
//グレースケール入力
cv::Mat src = cv::imread("img.png", cv::IMREAD_GRAYSCALE);
// 画像の読み込みに失敗したらエラー終了する
if (src.empty())
{
std::cerr << "Failed to open image file." << std::endl;
return -1;
}
// 二値化
cv::threshold(src, src, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
//ラべリング処理
cv::Mat LabelImg;
cv::Mat stats;
cv::Mat centroids;
int nLab = cv::connectedComponentsWithStats(src, LabelImg, stats, centroids);
/*単体テスト以外では必要ない*/
// ラベリング結果の描画色を決定
std::vector<cv::Vec3b> colors(nLab);
colors[0] = cv::Vec3b(0, 0, 0);
for (int i = 1; i < nLab; ++i) {
colors[i] = cv::Vec3b((rand() & 255), (rand() & 255), (rand() & 255));
}
/*単体テスト以外では必要ない*/
// ラベリング結果の描画
cv::Mat Dst(src.size(), CV_8UC3);
for (int i = 0; i < Dst.rows; ++i) {
int *lb = LabelImg.ptr<int>(i);
cv::Vec3b *pix = Dst.ptr<cv::Vec3b>(i);
for (int j = 0; j < Dst.cols; ++j) {
pix[j] = colors[lb[j]];
}
}
//ROIの設定
for (int i = 1; i < nLab; ++i) {
int *param = stats.ptr<int>(i);
int x = param[cv::ConnectedComponentsTypes::CC_STAT_LEFT];
int y = param[cv::ConnectedComponentsTypes::CC_STAT_TOP];
int height = param[cv::ConnectedComponentsTypes::CC_STAT_HEIGHT];
int width = param[cv::ConnectedComponentsTypes::CC_STAT_WIDTH];
cv::rectangle(Dst, cv::Rect(x, y, width, height), cv::Scalar(0, 255, 0), 2);
}
int a[2];
int b[2];
//重心の出力
for (int i = 1; i < nLab; ++i) {
double *param = centroids.ptr<double>(i);
int x = static_cast<int>(param[0]);
int y = static_cast<int>(param[1]);
cv::circle(Dst, cv::Point(x, y), 3, cv::Scalar(0, 0, 255), -1);
std::cout << "centroids " << i << " = (" << x << " , " << y << ")" << std::endl;
if (i == 1) {
a[0] = x;
b[0] = y;
}
else if (i == 2) {
a[1] = x;
b[1] = y;
}
}
//面積値の出力
for (int i = 1; i < nLab; ++i) {
int *param = stats.ptr<int>(i);
std::cout << "area " << i << " = " << param[cv::ConnectedComponentsTypes::CC_STAT_AREA] << std::endl;
//ROIの左上に番号を書き込む
int x = param[cv::ConnectedComponentsTypes::CC_STAT_LEFT];
int y = param[cv::ConnectedComponentsTypes::CC_STAT_TOP];
std::stringstream num;
num << i;
cv::putText(Dst, num.str(), cv::Point(x + 5, y + 20), cv::FONT_HERSHEY_COMPLEX, 0.7, cv::Scalar(0, 255, 255), 2);
}
cv::imshow("Src", src);
cv::imshow("Labels", Dst);
cv::waitKey();
while (System::Update())
{
/*
ここは後々追加予定です
*/
}
return 0;
}
Reputeless 2016/09/21(Wed) 23:27
解決されたようですが、説明を書きます。
[1]
Siv3D アプリの開発では void Main() 関数をエントリーポイントとします。
一般的な C++ プログラムの int main() は使えません。
[2]
Siv3D で OpenCV を使うには、OpenCV へのインクルードパスを通したうえで
# include <opencv2/opencv.hpp>
をインクルードしてください。
ライブラリファイルは Siv3D に付属しているものが使えるので、特別な操作は不要です。
Siv3D August 2016 v2 では OpenCV 3.0.0 に対応しています。
[3]
Siv3D に付属しない OpenCV モジュールの関数を使用した場合、リンカエラーになります。
その場合は必要なモジュールの .lib を追加でリンクしてください。
この際、OpenCV に最初から付属している .lib ファイルを使用するとランタイムエラーが生じることがあります。
お手数ですが、必要なモジュールの .lib ファイルを自前でビルドしてください。
(Debug 用は /MTd, Release 用は /MT オプションを選択してください。)
こちらも参考にしてください
http://siv3d.jp/bbs/patio.cgi?read=100&ukey=0