1

Objective-C で OpenCV 静的ライブラリを使用して画像処理を行っています。アプリは非常にうまく機能していますが、デバイス自体ではかなり遅いです。処理の大部分は実際には事前に行うことができるため、このデータをシリアル化し、代わりにアプリの起動時にそれをロードすることにしました。

シリアル化/アーカイブする必要があるデータは、タイプ CvSeq (openCV シーケンス - 値のシーケンスへのポインター) のオブジェクトにあります。私は基本的にこれをファイルに保存して、後でロードできるようにしたいと考えています。NSCoding プロトコルに準拠したクラスを作成し、そこからエンコード/デコードすることでこれを実行できると思いました。

@implementation MyObject

@synthesize point = _point;
@synthesize description = _description;

- (id)initWithCoder:(NSCoder *)decoder {
    if (self = [super init]) {
        self.point = [decoder decodeObjectForKey:@"point"];
        self.description = [decoder decodeObjectForKey:@"description"];
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.point forKey:@"point"];
    [encoder encodeObject:self.description forKey:@"description"];
}

@end

しかし、decodeObjectForKey: および encodeObject: 呼び出しでエラーが発生します

error: cannot convert 'objc_object*' to 'CvSeq*' in argument passing

私のコードに問題がありますか、それともオブジェクトにある非目的 C インスタンス変数で同じことを達成できるようにするには、別のルートを取る必要がありますか?

4

2 に答える 2

6

Objective-C's serialization code is not going to know how to archive your C++ classes. You're going to need to explicitly write code to do that. Assuming "description" is the CvSeq* in the above code, you will need to write methods that convert from CvSeq to something that Cocoa knows how to archive. An NSString is probably the easiest place to start, even if it's not the most efficient scheme.

NSString* NSStringFromCvSeq(CvSeq* cppObj)
{
    // You have to write this, but at it's simplest it might be something like...
    return [NSString stringWithFormat: @"%d|%d|%d", cppObj->foo, cppObj->bar, cppObj->baz];
}

CvSeq* NewCvSeqFromNSString(NSString* encodedString)
{
    // You have to write this, but at it's simplest it might be something like...
    NSScanner* scanner = [NSScanner scannerWithString: encodedString];
    [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString: @"|"]];
    int foo = [scanner scanInt];
    int bar = [scanner scanInt];
    int baz = [scanner scanInt];

    return new CvSeq(foo, bar, baz);
}

- (id)initWithCoder:(NSCoder *)decoder {
    if (self = [super init]) {
        self.point = [decoder decodeObjectForKey:@"point"];
        self.description = NewCvSeqFromNSString([decoder decodeObjectForKey:@"description"]);
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.point forKey:@"point"];
    [encoder encodeObject: NSStringFromCvSeq(self.description) forKey:@"description"];
}

The key takeaway here is that Cocoa has no idea how to archive arbitrary types (excepting Objective-C types that already adopt NSCoding), and will never archive a C++ object "for free" without some sort of glue layer, since a C++ object has no way of adopting the NSCoding protocol.

Hope that helps!

于 2011-04-12T16:23:48.763 に答える
1

独自のエンコーディング/シリアル化の代わりに、 dataWithBytes メソッドを使用した NSData クラスは、以下のように Objective-C の世界で OpenCV Mat データを処理するのに役立つ場合があります。

NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];

NSData クラスに転送した後、ファイルに保存できます。

于 2013-10-09T02:53:05.697 に答える