我尝试使用Core Image过滤器在我的Mac应用中为图像添加一些色彩校正。首先,我正在考虑允许自定义白平衡,从图像中删除强制转换。看起来CIWhitePointAdjust
正是我正在寻找的,但在尝试之后,我不确定我是否错误地使用它,或者它是不是做我想的。
从这张图片开始,随着年龄变黄,右边缘有一条白色的细条:
我应用过滤器,如下所示:
NSColor *whiteSample = // Chosen from the speech bubble's background
CIColor *whiteInputColor = [[CIColor alloc] initWithColor:whiteSample];
layer.filters = @[
[CIFilter filterWithName:@"CIWhitePointAdjust"
withInputParameters:@{kCIInputColorKey: whiteInputColor}]
];
并获取此图片:
请注意,它看起来比原始颜色更暗,更黄(与我想要的效果相反)。我一直期待一种效果更像是在Photoshop中执行自动颜色,如下所示:
我是否错误地使用CIWhitePointAdjust
,还是这项工作的错误工具?如果其他过滤器或过滤器组合效果更好,我很乐意知道。
由于我操作已经在CALayer
个对象中的图像,因此Core Image过滤器看起来确实是正确的选择,但如果这只能通过其他方式实现,我就会打开那个。
更新
信号处理网站上的helpful answer为我提供了我尝试实施的名称。从广义上讲,它被称为直方图均衡。我试图弄清楚是否有使用Core Image过滤器执行该过程的方法,到目前为止,它看起来并不太有希望(没有我自己编写)。
答案 0 :(得分:3)
好的,所以我想我已经把它钉了!这是我从https://stackoverflow.com/a/30447041/734860和几个胶水中捣乱的原因:
@import Accelerator;
// I haven't yet found a way to do it within Core Image
// use this when you need to CIImage* -> CGImageRef
CIImage *ciImage = [CIImage imageWithCGImage:cgImage];
...
// use this when you need to CGImageRef -> CIImage*
CIContext* context = [[CIContext alloc] init];
CGImageRef cgImage = [context createCGImage:ciImage fromRect:ciImage.extent];
...
// the algorithm itself, which uses vImage and has to convert to/from it via CGImage
CGImageRef CreateEqualisedCGImageFromCGImage(CGImageRef original)
{
vImage_Error err;
vImage_Buffer _img;
vImage_CGImageFormat format = {
.bitsPerComponent = 8,
.bitsPerPixel = 32,
.colorSpace = NULL,
.bitmapInfo = (CGBitmapInfo)kCGImageAlphaFirst,
.version = 0,
.decode = NULL,
.renderingIntent = kCGRenderingIntentDefault,
};
CGFloat width = CGImageGetWidth(original);
CGFloat height = CGImageGetHeight(original);
vImage_Buffer _dstA, _dstR, _dstG, _dstB;
err = vImageBuffer_InitWithCGImage(&_img, &format, NULL, original, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_InitWithCGImage error: %ld", err);
err = vImageBuffer_Init( &_dstA, height, width, 8 * sizeof( uint8_t ), kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_Init (alpha) error: %ld", err);
err = vImageBuffer_Init( &_dstR, height, width, 8 * sizeof( uint8_t ), kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_Init (red) error: %ld", err);
err = vImageBuffer_Init( &_dstG, height, width, 8 * sizeof( uint8_t ), kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_Init (green) error: %ld", err);
err = vImageBuffer_Init( &_dstB, height, width, 8 * sizeof( uint8_t ), kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageBuffer_Init (blue) error: %ld", err);
err = vImageConvert_ARGB8888toPlanar8(&_img, &_dstA, &_dstR, &_dstG, &_dstB, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageConvert_ARGB8888toPlanar8 error: %ld", err);
err = vImageEqualization_Planar8(&_dstR, &_dstR, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageEqualization_Planar8 (red) error: %ld", err);
err = vImageEqualization_Planar8(&_dstG, &_dstG, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageEqualization_Planar8 (green) error: %ld", err);
err = vImageEqualization_Planar8(&_dstB, &_dstB, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageEqualization_Planar8 (blue) error: %ld", err);
err = vImageConvert_Planar8toARGB8888(&_dstA, &_dstR, &_dstG, &_dstB, &_img, kvImageNoFlags);
if (err != kvImageNoError)
NSLog(@"vImageConvert_Planar8toARGB8888 error: %ld", err);
err = vImageContrastStretch_ARGB8888( &_img, &_img, kvImageNoError );
if (err != kvImageNoError)
NSLog(@"vImageContrastStretch_ARGB8888 error: %ld", err);
free(_dstA.data);
free(_dstR.data);
free(_dstG.data);
free(_dstB.data);
CGImageRef result = vImageCreateCGImageFromBuffer(&_img, &format, NULL, NULL, kvImageNoFlags, &err);
if (err != kvImageNoError)
NSLog(@"vImageCreateCGImageFromBuffer error: %ld", err);
free(_img.data);
return result;
}
解决方案的优点全部归https://stackoverflow.com/users/4735340/james-bush所示,但我看起来很长时间没有成功的面向图像的解决方案(与该问题中讨论的视频处理相反),我认为像这样的现成回复是相关的。寻找' AutoLevels'在OS X或iOS上让我无处可去,我希望这可能对其他人有用。
答案 1 :(得分:0)
尝试使用autoAdjustmentFilters or autoAdjustmentFiltersWithOptions获取可能的过滤器列表...可能是后者,以便您可以排除需要面部检测的过滤器,如果您打算自动调整卡通扫描。
答案 2 :(得分:0)
斯威夫特 5
string reverse(string str)
{
int k = str.length();
for (int j = 0; j < k / 2; j++)
{
swap(str[j], str[k - j - 1]);
}
return str;
}