Pergunta

Estou tentando fazer algum processamento de imagem no iPhone. estou a usar http://developer.apple.com/library/ios/#qa/qa2010/qa1702.html para capturar os quadros da câmera.

Meu problema é que, quando estou tentando acessar o buffer capturado, a câmera FPS cai de 30 para cerca de 20. Alguém sabe como eu posso corrigi -lo?

Eu uso a qualidade mais baixa de captura que encontrei (AVCAPTUSESSESSOPRETLOW = 192X144) no formato kcvpixelformattype_32bgra. Se alguém souber uma qualidade mais baixa que eu poderia usar, estou disposto a experimentá -lo.

Quando faço o mesmo acesso de imagem em outras plataformas, como o Symbian, ele funciona bem.

Aqui está o meu código:

#pragma mark -
#pragma mark AVCaptureSession delegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
    fromConnection:(AVCaptureConnection *)connection 
{ 
 /*We create an autorelease pool because as we are not in the main_queue our code is
  not executed in the main thread. So we have to create an autorelease pool for the thread we are in*/
 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
 //Lock the image buffer
    if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess)
    {  

  // calculate FPS and display it using main thread
  [self performSelectorOnMainThread:@selector(updateFps:) withObject: (id) nil waitUntilDone:NO];


  UInt8 *base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address

  size_t width  = CVPixelBufferGetWidth(imageBuffer); 
  size_t height = CVPixelBufferGetHeight(imageBuffer);

  int size = (height*width);
  UInt8* pRGBtmp = m_pRGBimage;

        /*
        Here is the problem; m_pRGBimage is RGB image I want to process.
        In the 'for' loop I convert the image from BGRA to RGB. As a resault, the FPS drops to 20.
        */ 
  for (int i=0;i<size;i++)
  {   
    pRGBtmp[0] = base[2];
    pRGBtmp[1] = base[1];
    pRGBtmp[2] = base[0];
    base = base+4;
    pRGBtmp = pRGBtmp+3;     
  }


  // Display received action
  [self performSelectorOnMainThread:@selector(displayAction:) withObject: (id) nil waitUntilDone:NO];
  //[self displayAction:&eyePlayOutput];
  //saveFrame( imageBuffer );

  //unlock the  image buffer
  CVPixelBufferUnlockBaseAddress(imageBuffer,0);

 }


 [pool drain];
} 

Como acompanhamento das respostas, preciso processar a imagem em tempo real, ela está sendo exibida.

Percebi que, quando uso o AVCAPTUSESSESSESTHETHUTH, a coisa mais simples que faço, como:

 for (int i=0;i<size;i++)
    x = base[0];

faz com que a taxa de quadros caia para 4-5 fps. Eu acho que é porque uma imagem nesse tamanho não é armazenada em cache.

Basicamente, preciso de 96x48 imagem. Existe uma maneira simples de reduzir a imagem da saída da câmera, uma maneira de usar aceleração de hardware, para que eu possa trabalhar com a pequena?

Foi útil?

Solução

Qualquer coisa que itera sobre todos os pixels de uma imagem será bastante lenta em todos os dispositivos mais rápidos do iOS. Por exemplo, comparei a iteração de cada pixel em uma estrutura de vídeo de 640 x 480 (307.200 pixels) com um teste de cores por pixel simples e descobri que isso funciona apenas a cerca de 4 fps em um iPhone 4.

Você está olhando para o processamento de 27.648 pixels no seu caso, o que deve correr rápido o suficiente para atingir 30 qps em um iPhone 4, mas esse é um processador muito mais rápido do que o que estava no iPhone e iPhone 3G original. O iPhone 3G provavelmente ainda lutará com essa carga de processamento. Você também não diz a rapidez com que o processador foi em seus dispositivos simbianos.

Eu sugiro reformular seu algoritmo de processamento para evitar a conversão do espaço de cores. Não deve haver necessidade de reordenar os componentes de cores para processá -los.

Além disso, você pode processar seletivamente apenas alguns pixels, amostragem em determinados intervalos nas linhas e colunas da imagem.

Por fim, se você estiver segmentando os dispositivos iOS mais recentes que têm suporte para o OpenGL ES 2.0 (iPhone 3G S e mais recente), convém usar um shader de fragmento GLSL para processar o quadro de vídeo inteiramente na GPU. Eu descrevo o processo aqui, juntamente com o código de amostra para rastreamento de objetos baseado em cores em tempo real. A GPU pode lidar com esse tipo de processamento 14 - 28 vezes mais rápido que a CPU, nos meus benchmarks.

Outras dicas

Isenção de responsabilidade: Esta resposta é um palpite :)

Você está fazendo muito trabalho enquanto o buffer está bloqueado; Isso está segurando o fio que está capturando a imagem da câmera?

Você poderia copiar os dados do buffer enquanto trabalha nele para poder desbloqueá -los o mais rápido possível

if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess) {
    // Get the base address and size of the buffer
    UInt8 *buffer_base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address
    size_t width  = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer);

    // Copy it's contents out
    Uint8 *base = malloc(width * height * 4);
    memcpy(base, buffer_base, size);

    // Unlock the buffer
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);

    // base now points to a copy of the buffers' data - do what you want to it . . .
    ...

    // remember to free base once you're done ;)
    free(base);

Se for a fechadura que está segurando a captura, isso deve ajudar.

NB Você pode acelerar isso se souber que todos os buffers terão o mesmo tamanho.


Ou se esse não for o problema, você pode tentar diminuir a prioridade deste tópico

[NSThread setThreadPriority:0.25];

Copie o conteúdo do quadro da câmera em um buffer dedicado e opere a partir daí. Isso resulta em uma grande melhoria de velocidade na minha experiência. Meu melhor palpite é que a região da memória onde o quadro da câmera está localizado possui proteções especiais que tornam lentamente os acessos de leitura/escrita.

Confira o endereço de memória dos dados do quadro da câmera. No meu dispositivo, o buffer da câmera está em 0x63ac000. Isso não significa nada para mim, exceto que os outros objetos de heap estão em endereços mais próximos de 0x1300000. A sugestão da trava não resolveu minha desaceleração, mas o memcpy fez.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top