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 的序列化代码不会知道如何归档您的 C++ 类。您将需要显式地编写代码来做到这一点。假设“描述”是上述代码中的 CvSeq*,您将需要编写从 CvSeq 转换为 Cocoa 知道如何归档的方法的方法。NSString 可能是最容易开始的地方,即使它不是最有效的方案。

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"];
}

这里的关键点是 Cocoa 不知道如何归档任意类型(除了已经采用 NSCoding 的 Objective-C 类型),并且在没有某种粘合层的情况下永远不会“免费”归档 C++ 对象,因为 C++ 对象具有没有办法采用 NSCoding 协议。

希望有帮助!

于 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 回答