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;
}
記事編集
keni  2016/09/21(Wed) 15:09
投稿した者です。

先ほどこの問題について解決しました。
失礼いたしました。
編集
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
編集
hidemi yamachi  2023/07/07(Fri) 17:13
Kinectを使ったアプリで動画再生をしたいため、旧Siv3dとOpenCVを使ってプログラムを作っています。
https://siv3d.jp/bbs/patio.cgi?read=165 にあるコードは動きましたが、作成した以下のコードは、ファイルオープンで失敗します。

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>
# include <Siv3D.hpp>

void Main()
{
//#define WINDOW_NAME "Video"
//cv::namedWindow(WINDOW_NAME, cv::WINDOW_NORMAL);
cv::VideoCapture cap("フィジカルトレーニング.mp4");
//cv::moveWindow(WINDOW_NAME, 0, 0);
//cv::setWindowProperty(WINDOW_NAME, cv::WND_PROP_FULLSCREEN, 1);//cv::WINDOW_FULLSCREEN); //フルスクリーンにする
if (!cap.isOpened())
{
MessageBox::Show(L"初期化に失敗しました");
return;
}

int v_w = cap.get(cv::CAP_PROP_FRAME_WIDTH); //縦の大きさ
int v_h = cap.get(cv::CAP_PROP_FRAME_HEIGHT); //横の大きさ
int max_frame = cap.get(cv::CAP_PROP_FRAME_COUNT); //フレーム数
int fps = cap.get(cv::CAP_PROP_FPS); //フレームレート

cv::Mat_<cv::Vec3b> frame;
Image image;
DynamicTexture texture;

while (System::Update())
{
//if (cap.grab() && cap.retrieve(frame))
{
cap >> frame;
image.resize(v_w, v_h, Palette::Black);

Color* pDst = image[0];
const Color* pDstEnd = pDst + image.num_pixels;
uint8* pSrc = frame.data;

while (pDst != pDstEnd)
{
pDst->b = *(pSrc++);
pDst->g = *(pSrc++);
pDst->r = *(pSrc++);
++pDst;
}

texture.fill(image);
if (texture)
{
texture.draw();
}
}
}
}

何が原因か、教えていただけると助かります。

ちなみにOpenSiv3DでKinectを使えるようになるのはいつごろになるのでしょうか。
編集
Reputeless  2023/07/08(Sat) 17:05
(1)
> 何が原因か、教えていただけると助かります。

旧 Siv3D がリンクする OpenCV の静的ライブラリ(.lib)では、ファイルサイズ削減のため画像や動画をデコードする機能が無効化されていたと記憶しています。
したがってデコードが必要な画像ファイルや動画ファイルはオープンできません。

リンクする .lib を、MP4 を読み込めるビルド設定でビルドした同一バージョンの OpenCV の .lib に置き換えることで、期待した動作になると思われます。
参考: https://github.com/Siv3D/Reference-JP/wiki/OpenCV

(2)
> ちなみにOpenSiv3DでKinectを使えるようになるのはいつごろになるのでしょうか。

直近での実装予定はありませんが、v0.8 世代で実装したいと思っています。
急ぎの実装リクエストであれば有償で対応できます。必要な要件と希望納期をまとめ、開発者 (reputeless at gmail.com) までコンタクトしてください。
編集
hidemi yamachi  2023/07/09(Sun) 13:41
さっそくご回答いただきありがとうございます。

OpenCVのスタティックライブラリをビルドし、Siv3D(August2016v2_VS2019)\Lib\x64\OpenCV にある.libファイルと差し替えるということでよろしいでしょうか。

OpenCVにあるスタティックライブラリからopencv_videoio.libを差し替えればいいかと考えたのですが、MSVCのバージョンが違うというエラーが出ました。
MSVC v140でビルドすればよいということでしょうか。

Kinectの実装については、自分でOpenSiv3dに組み込んでみようと検討中です。
その結果で開発のお願いを検討したいと思います。
編集
Reputeless  2023/07/12(Wed) 12:22
> OpenCVのスタティックライブラリをビルドし、Siv3D(August2016v2_VS2019)\Lib\x64\OpenCV にある.libファイルと差し替えるということでよろしいでしょうか。

はい。

> MSVC v140でビルドすればよいということでしょうか。

はい。Siv3D 2016 August v2 は VS2015 でビルドしていたと思うので、v140 でビルドしてください。

> Kinectの実装

Siv3D 2016 August v2 の Kinect V1 のコードです。参考にしてください。
https://gist.github.com/Reputeless/1c7c49fa4e0a9cbd60591d56f9d168ec
編集
hidemi yamachi  2023/07/12(Wed) 12:51
ご回答をいただきありがとうございます。
試してみます。

実は大学の授業で障害児向けのKinectを使ったフィジカルトレーニングアプリを作成しています。
特別支援学校の先生方からいろいろと要望を受けていて、OpenSiv3Dの新しい機能を使いたいと思いながら、Kinectが使えないため旧Siv3Dでやっています。
OpenSiv3DでのKinectのサポートを心待ちにしています。
編集
件名
Re: Siv3Dとopencvの併用について
名前
コメント
画像添付


投稿修正キー (投稿を修正する時に使います)
画像認証 (右画像の数字を入力) 投稿キー

- WEB PATIO -