Как найти края изображения с его цветами в iphone?

Я работаю над приложением, которое связано с изменением цветового эффекта в изображении. Я сделал почти все. Теперь проблема в том, что в одном из эффектов я должен дать эффект, подобный фильтру светящихся краев в фотошопе. Этот фильтр обтекает края изображения своим цветом, а остальные цвета изображения черными. Используя BradLarson GPU Image GPUImageSobelEdgeDetectionFilter или GPUImageCannyEdgeDetectionFilter, я могу найти края, но с краями белого цвета, и мне нужно найти края в цветах. Есть ли у них другой способ найти края в цвете с помощью GPUImage или openCV. Любая помощь будет очень полезна для меня. Спасибо


person Surjeet    schedule 03.10.2013    source источник
comment
Конечно. Вы можете создавать пользовательские фильтры на основе фильтров обнаружения краев в GPUImage, заменяя белый цвет собственным управляемым цветом. Несколько человек сделали это, и для этого требуется лишь несколько настроек кода шейдера.   -  person Brad Larson    schedule 04.10.2013
comment
@BradLarson: спасибо за ответ, но нужна дополнительная помощь. Как я могу получить исходный цвет краев, как на изображении. Пожалуйста, объясните это. Это будет очень полезно.   -  person Surjeet    schedule 11.10.2013


Ответы (1)


Вы действительно обязаны поиграть с написанием пользовательских шейдеров. Это чрезвычайно доступно и может очень быстро стать мощным, если вы приложите усилия.

Тем не менее, я думаю, что вы пытаетесь получить что-то вроде этого результата:

Есть много приемлемых способов добраться сюда, но написание пользовательского шейдера для подкласса GPUImageTwoInputFilter с последующим нацеливанием на него как исходного изображения, так и изображения edgeDetection — вот как я достиг картинки, которую вы видите здесь.

Подкласс будет выглядеть примерно так:

#import "OriginalColorEdgeMixer.h"


//Assumes you have targeted this filter with the original image first, then with an edge detection filter that returns white pixels on edges
//We are setting the threshold manually here, but could just as easily be a GLint which is dynamically fed at runtime

#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kOriginalColorEdgeMixer = SHADER_STRING
(
 varying highp vec2 textureCoordinate;
 varying highp vec2 textureCoordinate2;

 uniform sampler2D inputImageTexture;
 uniform sampler2D inputImageTexture2;

 lowp float threshold;
 mediump float resultingRed;
 mediump float resultingGreen;
 mediump float resultingBlue;

 void main()
 {
     mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
     mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
     threshold = step(0.3, textureColor2.r);

     resultingRed = threshold * textureColor.r;
     resultingGreen = threshold * textureColor.g;
     resultingBlue = threshold *textureColor.b;

     gl_FragColor = vec4(resultingRed, resultingGreen, resultingBlue, textureColor.a);
 }
 );
#else
NSString *const kGPUImageDifferenceBlendFragmentShaderString = SHADER_STRING
(
 varying vec2 textureCoordinate;
 varying vec2 textureCoordinate2;

 uniform sampler2D inputImageTexture;
 uniform sampler2D inputImageTexture2;

 float threshold;
 float resultingRed;
 float resultingGreen;
 float resultingBlue;

 void main()
 {
     vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
     vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
     threshold = step(0.3,textureColor2.r);

     resultingRed = threshold * textureColor.r;
     resultingGreen = threshold * textureColor.g;
     resultingBlue = threshold *textureColor.b;

     gl_FragColor = vec4(resultingRed, resultingGreen, resultingBlue, textureColor.a);
 }
 );
#endif

@implementation OriginalColorEdgeMixer

- (id)init;
{
    if (!(self = [super initWithFragmentShaderFromString:kOriginalColorEdgeMixer]))
    {
        return nil;
    }

    return self;
}

@end

Поскольку я писал это, мы ожидаем, что выход фильтра edgeDetection будет вторым входом этого пользовательского фильтра.

Я произвольно выбрал пороговое значение 0,3 для интенсивности на изображении edgeDetection, чтобы исходный цвет был виден. Это можно легко сделать динамическим, привязав его к GLint, полученному из UISlider в вашем приложении (много примеров этого в примере кода Брэда)

Для ясности для людей, которые только начинают работать с GPUImage, использовать написанный вами пользовательский фильтр очень просто. Я сделал это так:

[self configureCamera];

edgeDetection = [[GPUImageSobelEdgeDetectionFilter alloc] init];
edgeMixer = [[OriginalColorEdgeMixer alloc] init];

[camera addTarget:edgeDetection];
[camera addTarget:edgeMixer];
[edgeDetection addTarget:edgeMixer];
[edgeMixer addTarget:_previewLayer];

[camera startCameraCapture];

Подводя итог, не бойтесь начинать писать собственные шейдеры! Кривая обучения коротка, а ошибки, выдаваемые отладчиком, чрезвычайно полезны, позволяя вам точно знать, где вы испортили синтаксис.

Наконец, это отличное место для документации по синтаксису и использованию специальных функций OpenGL

person ryan cumley    schedule 15.10.2013
comment
Это работает для меня, и это работает отвратительно, что я хочу. Я пытался создать собственный фильтр, но не смог. Вы решаете мою проблему. Так что большое спасибо, Райан Камли. - person Surjeet; 16.10.2013
comment
Не за что! Программирование исключительно терпимо к повторяющимся циклам «попытка-неудача», поэтому не расстраивайтесь, если ваши первые несколько попыток не увенчаются успехом. Настраивайте и пробуйте снова, пока не добьетесь успеха, мы все так делаем... - person ryan cumley; 16.10.2013