1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Cocos2d-xでOpenCVを使ってみたかったけど.....

Last updated at Posted at 2015-05-31

今回は、OpenCVをcocos2d-xで使おうと思ったけどダメだったというお話です。
前回に続き、cocos2d-xを触っていたのですが、動画再生用のノードがcocos2d-xってないみたいですね。

そこで、私の得意分野なOpenCVを使って動画ファイルからSpriteのリストを作成してアニメーションさせようと考えて実装してみました。

VideoNode.h
#import <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <2d/CCAnimation.h>


class VideoNode
{
public:
    static VideoNode* create();
    void initWithFile(const std::string &fileName);
    void play(bool repeat);
    cocos2d::Sprite* getSprite(){
        return this->sprite;
    }
private:
    void splitMovie(const std::string fileName, std::vector<cv::Mat> &mVec);
    void cvMat2ccImage(cv::Mat &src, cocos2d::Image &dst);
    cocos2d::Sprite* sprite;
    cocos2d::Animate *action;
};

実装部分は

VideoNode.cpp

#include "VideoNode.h"


VideoNode* VideoNode::create()
{
    VideoNode* node = new (std::nothrow)VideoNode();
    
    return node;
}

void VideoNode::initWithFile(const std::string &fileName)
{
    //MP4のfileNameから画像バッファを取得
    
    std::vector<cv::Mat> images;
    splitMovie(fileName, images);
    
//    //アニメーションクラスの作成
    auto animation = cocos2d::Animation::create();
//    
//    //ループでアニメーションクラスにaddSpriteFrameしていく
//    
    for (int i=0; i < images.size(); i++) {
        //newで動的にImage分のメモリを確保
        cocos2d::Image *img = new cocos2d::Image();
        cv::Mat m = images[i];
        //確保したimgのアドレスの中身を渡す。
        cvMat2ccImage(m, *img);

        cocos2d::Texture2D *tex = new cocos2d::Texture2D();
        tex->initWithImage(img);
        auto rect = new cocos2d::Rect();
        rect->setRect(0, 0, img->getWidth(), img->getHeight());
        cocos2d::SpriteFrame *frame = cocos2d::SpriteFrame::createWithTexture(tex, *rect);
        if(i==0){
            cocos2d::Sprite *sprite = cocos2d::Sprite::createWithSpriteFrame(frame);
            sprite->setName("animSprite");
            this->sprite = sprite;
        }
        animation->addSpriteFrame(frame);
   }
    action = cocos2d::Animate::create(animation);
    
}

void VideoNode::play(bool repeat)
{
    auto anime = cocos2d::RepeatForever::create(action);
    this->sprite->runAction(anime);
}

//cvMatからcocos2d::Imageに変換するメソッド
void VideoNode::cvMat2ccImage(cv::Mat &src, cocos2d::Image &dst)
{
    unsigned char *srcData;
    int width = src.cols;
    int height = src.rows;

    
    srcData = (unsigned char *)src.data;
    unsigned long size = 3 * width * height;
    dst.initWithRawData(srcData, size, width, height, 24);
}

//映像からcv::Matのデータ群を取得するメソッド
void VideoNode::splitMovie(const std::string fileName, std::vector<cv::Mat> &mVec)
{
    CvCapture *capture = cvCreateFileCapture(fileName.c_str());
    if(!capture)
    {
        std::cerr << "cvCreateFileCapure filed" << std::endl;
    }
    
    int rows = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
    int cols = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
    
    
    IplImage *frame =NULL;
    cv::Mat m(rows, cols, CV_8UC3);
    
    while ((frame=cvQueryFrame(capture))!=NULL) {
        m = cv::cvarrToMat(frame);
        mVec.push_back(m);
    }
}

みたいな感じで実装してみました。これでいける!って思ったんですけど

スクリーンショット 2015-06-01 4.31.16.png

なんで、何も表示されない!?

コンソールを見てみるとなんかwarningがでてる

jpeg error: Wrong JPEG library version: library is 62, caller expects 90
size = 0

とか、

libpng warning: Application built with libpng-1.6.16 but running with 1.5.12

とかでてるよ....

どうも調べてみるとOpenCVではビルド時にlibpng 1.5.12使ってて、cocos2d-xはlibpng 1.6.16使ってるのが原因っぽそう。

でもiOS向けにOpenCVビルドし直せば行けるかな?って思ったけどlibpngとlibjpegどうやって指定すればいいか分からないんで結局できないよ。

ってなりました。

誰か良い解決案がありましたらぜひ教えてください。

2015.6.14追記
解決法とコードを修正したものまとめましたので
ここを見てください。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?