1

ドキュメントにあるコードは次のとおりです。

int myEmboss(void *inData,
unsigned int inRowBytes,
void *outData,
unsigned int outRowBytes,
unsigned int height,
unsigned int width,
void *kernel,
unsigned int kernel_height,
unsigned int kernel_width,
int divisor ,
vImage_Flags flags ) {
   uint_8 kernel = {-2, -2, 0, -2, 6, 0, 0, 0, 0}; // 1
   vImage_Buffer src = { inData, height, width, inRowBytes }; // 2
   vImage_Buffer dest = { outData, height, width, outRowBytes }; // 3
   unsigned char bgColor[4] = { 0, 0, 0, 0 }; // 4
   vImage_Error err; // 5
   err = vImageConvolve_ARGB8888(    &src,     //const vImage_Buffer *src
                                     &dest,    //const vImage_Buffer *dest,
                                      NULL,
                                      0,    //unsigned int srcOffsetToROI_X,
                                      0,    //unsigned int srcOffsetToROI_Y,
                                      kernel,    //const signed int *kernel,
                                      kernel_height,     //unsigned int
                                      kernel_width,    //unsigned int
                                      divisor,    //int
                                      bgColor,
                                      flags | kvImageBackgroundColorFill
                                      //vImage_Flags flags
                                    );


   return err;
}

ここに問題があります: カーネル変数は 3 つの異なる型を参照しているようです:

  1. void * 仮パラメーター リストのカーネル
  2. 未定義の unsigned int uint_8 カーネル。おそらく仮パラメーターをシャドウする新しい変数として
  3. vImageConvolve_ARGB8888 を呼び出すときの const signed int *kernel。

これは実際のコードですか?この関数をコンパイルするにはどうすればよいですか?

4

3 に答える 3

2

その機能がかなりめちゃくちゃであることは正しいです。Provide Feedback ウィジェットを使用して Apple に知らせることをお勧めします。

関数シグネチャからkernelkernel_width、およびパラメータを削除する必要があると思います。kernel_heightこれらは、呼び出し元が提供するカーネルを適用する関数からの持ち越しのように見えますが、この例は内部定義のカーネルを適用することに関するものです。

kernelの配列になるようにローカル変数の宣言を修正しました。次のuint8_tようにします。

    uint8_t kernel[] = {-2, -2, 0, -2, 6, 0, 0, 0, 0}; // 1

次に、 の呼び出しで、 とを置き換えvImageConvolve_ARGB8888()ます。カーネルはハードコーディングされているため、次元も同じようにできます。kernel_widthkernel_height3

于 2013-09-20T23:16:56.250 に答える
2

これは、AVAssetReader を使用してビデオから読み取ったフレームを処理するために使用している方法です。これは曖昧ですが、ニーズに合わせてカーネルを変更できます。「imageData」はもちろん、UIImage などの他の手段で取得できます。

     CMSampleBufferRef sampleBuffer = [asset_reader_output copyNextSampleBuffer];
     CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);            
     CVPixelBufferLockBaseAddress(imageBuffer,0);
     void *imageData = CVPixelBufferGetBaseAddress(imageBuffer);        

     int16_t kernel[9];
     for(int i = 0; i < 9; i++) {
        kernel[i] = 1;
     }
     kernel[4] = 2;

     unsigned char *newData= (unsigned char*)malloc(4*currSize);

     vImage_Buffer  inBuff = { imageData, height, width, 4*width };
     vImage_Buffer  outBuff = { newData, height, width, 4*width };

     vImage_Error err=vImageConvolve_ARGB8888 (&inBuff,&outBuff,NULL, 0,0,kernel,3,3,10,nil,kvImageEdgeExtend);
     if (err != kvImageNoError) NSLog(@"convolve error %ld", err);
     CVPixelBufferUnlockBaseAddress(imageBuffer, 0);

     //newData holds the processed image
于 2013-09-15T18:27:19.080 に答える
2

カーネルは、たたみ込みで使用される単なるカーネルです。数学的に言えば、ぼかし/シャープ/エンボスまたはその他の効果を実現するために、画像に畳み込まれるのは行列です。あなたが提供したこの関数は、vimage畳み込み関数の薄いラッパーです。実際に畳み込みを実行するには、以下のコードに従うことができます。コードはすべて手作業で入力されているため、必ずしも 100% 正しいとは限りませんが、正しい方向を示しているはずです。

この関数を使用するには、まず画像へのピクセル アクセスが必要です。UIImage があると仮定すると、次のようにします。

//image is a UIImage
CGImageRef img = image.CGImage;
CGDataProviderRef dataProvider = CGImageGetDataProvider(img); 
CFDataRef cfData = CGDataProviderCopyData(dataProvider);
void * dataPtr = (void*)CFDataGetBytePtr(cfData);

次に、関数に渡す vImage_Buffer を作成します

vImage_Buffer inBuffer, outBuffer;
inBuffer.data = dataPtr;
inBuffer.width = CGImageGetWidth(img);
inBuffer.height = CGImageGetHeight(img);
inBuffer.rowBytes = CGImageGetBytesPerRow(img);

outBuffer も割り当てます

outBuffer.data = malloc(inBuffer.height * inBuffer.rowBytes)
// Setup width, height, rowbytes equal to inBuffer here

次に、例と同じカーネルを作成します。これは 3x3 行列です 値が float の場合は除数を掛けます (int である必要があります)

int divisor = 1000;
CGSize kernalSize = CGSizeMake(3,3);
int16_t *kernel = (int16_t*)malloc(sizeof(int16_t) * 3 * 3);
// Assign kernel values to the emboss kernel
// uint_8 kernel = {-2, -2, 0, -2, 6, 0, 0, 0, 0} // * 1000 ;

画像に対して畳み込みを実行します。

//Use a background of transparent black as temp
Pixel_8888 temp = 0;
vImageConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, kernel, kernelSize.width, kernelSize.height, divisor, temp, kvImageBackgroundColorFill);

outBuffer から新しい UIImage を作成して完了です。

カーネルと outBuffer データを解放することを忘れないでください。

于 2013-09-20T21:10:14.503 に答える