Мы пытаемся нормализовать UIImage
, чтобы его можно было правильно передать в модель CoreML.
Способ, которым мы получаем значения RGB для каждого пикселя, - это сначала инициализировать массив [CGFloat]
, называемый rawData
значений для каждого пикселя, так что есть позиция для цветов Красный, Зеленый, Синий иальфа-значение.В bitmapInfo
мы получаем необработанные значения пикселей из самого исходного изображения UIimage и проводим их.Используется для заполнения параметра bitmapInfo
в context
, переменной CGContext
.Позже мы будем использовать переменную context
для draw
a CGImage
, которая позже преобразует нормализованный CGImage
обратно в UIImage
.
Использование вложенного цикла for с итерацией координат x
и y
, минимальных и максимальных значений цвета пикселей среди всех цветов (найденных в массиве необработанных данных CGFloat
) по всем пикселямнайдены.Связанная переменная устанавливается для завершения цикла for, в противном случае она будет иметь ошибку вне диапазона.
range
указывает диапазон возможных значений RGB (т. Е. Разницу между максимальным значением цвета и минимальным).
Использование уравнения для нормализации каждого значения пикселя:
A = Image
curPixel = current pixel (R,G, B or Alpha)
NormalizedPixel = (curPixel-minPixel(A))/range
и аналогичный метод, разработанный для цикла сверху, для анализа массива rawData
и изменения цветов каждого пикселя в соответствии с этимнормализация.
Большинство наших кодов:
- UIImage для UIColor массив цветов пикселей
- Изменить цвет определенногопикселей в UIImage
- https://gist.github.com/pimpapare/e8187d82a3976b851fc12fe4f8965789
Мы используем CGFloat
вместо UInt8
, потому что нормализованные значения пикселей должны быть действительными числами от 0 до 1,не 0 или 1.
func normalize() -> UIImage?{
let colorSpace = CGColorSpaceCreateDeviceRGB()
guard let cgImage = cgImage else {
return nil
}
let width = Int(size.width)
let height = Int(size.height)
var rawData = [CGFloat](repeating: 0, count: width * height * 4)
let bytesPerPixel = 4
let bytesPerRow = bytesPerPixel * width
let bytesPerComponent = 8
let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue & CGBitmapInfo.alphaInfoMask.rawValue
let context = CGContext(data: &rawData,
width: width,
height: height,
bitsPerComponent: bytesPerComponent,
bytesPerRow: bytesPerRow,
space: colorSpace,
bitmapInfo: bitmapInfo)
let drawingRect = CGRect(origin: .zero, size: CGSize(width: width, height: height))
context?.draw(cgImage, in: drawingRect)
let bound = rawData.count
//find minimum and maximum
var minPixel: CGFloat = 1.0
var maxPixel: CGFloat = 0.0
for x in 0..<width {
for y in 0..<height {
let byteIndex = (bytesPerRow * x) + y * bytesPerPixel
if(byteIndex > bound - 4){
break
}
minPixel = min(CGFloat(rawData[byteIndex]), minPixel)
minPixel = min(CGFloat(rawData[byteIndex + 1]), minPixel)
minPixel = min(CGFloat(rawData[byteIndex + 2]), minPixel)
minPixel = min(CGFloat(rawData[byteIndex + 3]), minPixel)
maxPixel = max(CGFloat(rawData[byteIndex]), maxPixel)
maxPixel = max(CGFloat(rawData[byteIndex + 1]), maxPixel)
maxPixel = max(CGFloat(rawData[byteIndex + 2]), maxPixel)
maxPixel = max(CGFloat(rawData[byteIndex + 3]), maxPixel)
}
}
let range = maxPixel - minPixel
print("minPixel: \(minPixel)")
print("maxPixel : \(maxPixel)")
print("range: \(range)")
for x in 0..<width {
for y in 0..<height {
let byteIndex = (bytesPerRow * x) + y * bytesPerPixel
if(byteIndex > bound - 4){
break
}
rawData[byteIndex] = (CGFloat(rawData[byteIndex]) - minPixel) / range
rawData[byteIndex+1] = (CGFloat(rawData[byteIndex+1]) - minPixel) / range
rawData[byteIndex+2] = (CGFloat(rawData[byteIndex+2]) - minPixel) / range
rawData[byteIndex+3] = (CGFloat(rawData[byteIndex+3]) - minPixel) / range
}
}
let cgImage0 = context!.makeImage()
return UIImage.init(cgImage: cgImage0!)
}
До нормализации мы ожидаем, что диапазон значений пикселей равен 0 - 255, а после нормализации диапазон значений пикселей равен 0 - 1.
Формула нормализацииспособен нормализовать значения пикселей до значений от 0 до 1. Но когда мы пытаемся распечатать (просто добавляем операторы печати, когда мы перебираем значения пикселей) значения пикселей перед нормализацией, чтобы убедиться, что мы получаем необработанные значения пикселейПрямо, мы обнаружили, что диапазон этих значений выключен.Например, значение пикселя имеет значение 3.506e + 305 (больше 255.) Мы думаем, что вначале мы получаем неправильное значение необработанного пикселя.
Мы не знакомы с обработкой изображений в Swift и не уверены в правильности всего процесса нормализации.любая помощь будет оценена!