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
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