実現したいこと
swiftでの画像二値化アプリの開発
前提
swiftで画像二値化アプリの開発を行なっています。
現在、画像を読み込んで二値化することまではできているのですが、スライダーによる閾値の変化を行うことができていません。
開発、質問ともに初心者であるため、見にくい点などあると思いますがお力添えをいただけると幸いです。
発生している問題・エラーメッセージ
スライダーを動かしても、二値化した画像が変化しない。
該当のソースコード
swift
1// 2// ContentView.swift 3// Image_Swift 4// 5// 6 7import SwiftUI 8import UIKit 9 10extension UIImage { 11 func createBinarizedImage(r:[CGFloat], g: [CGFloat], b:[CGFloat], a:[CGFloat], threshold:CGFloat) -> UIImage{ 12 UIGraphicsBeginImageContextWithOptions(size, false, 0) 13 let wid:Int = Int(size.width) 14 let hei:Int = Int(size.height) 15 for w in 0..<wid { 16 for h in 0..<hei { 17 let index = (w * wid) + h 18 var color = 0.2126 * r[index] + 0.7152 * g[index] + 0.0722 * b[index] 19 if color > threshold / 100 { 20 color = 255 21 } else { 22 color = 0 23 } 24 UIColor(red: color, green: color, blue: color, alpha: a[index]).setFill() 25 let drawRect = CGRect(x: w, y: h, width: 1, height: 1) 26 UIRectFill(drawRect) 27 draw(in: drawRect, blendMode: .destinationIn, alpha: 1) 28 } 29 } 30 let binarizeImage = UIGraphicsGetImageFromCurrentImageContext()! 31 UIGraphicsEndImageContext() 32 return binarizeImage 33 34 } 35} 36 37class ViewController: UIViewController { 38 @IBOutlet weak var image: UIImageView! 39 40 var r:[CGFloat] = [] 41 var g:[CGFloat] = [] 42 var b:[CGFloat] = [] 43 var a:[CGFloat] = [] 44 45 var threshold:CGFloat = 0.0 46 47 override func viewDidLoad() { 48 super.viewDidLoad() 49 let img = UIImage(named: "Lena")! 50 51 // ピクセルごとの色情報の取得、下記のPixelBufferクラスの関数を使用している。 52 if let pixelBuffer = PixelBuffer(uiImage: img) { 53 for x in 0..<pixelBuffer.width { 54 for y in 0..<pixelBuffer.height { 55 r.append(pixelBuffer.getRed(x: x, y: y)) 56 g.append(pixelBuffer.getBlue(x: x, y: y)) 57 b.append(pixelBuffer.getGreen(x: x, y: y)) 58 a.append(pixelBuffer.getAlpha(x: x, y: y)) 59 } 60 } 61 } else { 62 print("image not format") 63 } 64 65 image.image = img.createBinarizedImage(r: r, g: g, b: b, a: a, threshold: threshold) 66 67 } 68} 69 70class PixelBuffer { 71 private var pixelData: Data 72 var width: Int 73 var height: Int 74 private var bytesPerRow: Int 75 private let bytesPerPixel = 4 //1ピクセルが4バイトのデータしか扱わない 76 77 init?(uiImage: UIImage) { 78 guard let cgImage = uiImage.cgImage, 79 //R,G,B,A各8Bit 80 cgImage.bitsPerComponent == 8, 81 //1 pixelが32bit 82 cgImage.bitsPerPixel == bytesPerPixel * 8 else { 83 return nil 84 85 } 86 pixelData = cgImage.dataProvider!.data! as Data 87 width = cgImage.width 88 height = cgImage.height 89 bytesPerRow = cgImage.bytesPerRow 90 } 91 92 func getRed(x: Int, y: Int) -> CGFloat { 93 let pixelInfo = bytesPerRow * y + x * bytesPerPixel 94 let r = CGFloat(pixelData[pixelInfo]) / CGFloat(255.0) 95 96 return r 97 } 98 func getGreen(x: Int, y: Int) -> CGFloat { 99 let pixelInfo = bytesPerRow * y + x * bytesPerPixel 100 let green = CGFloat(pixelData[pixelInfo+1]) / CGFloat(255.0) 101 102 return green 103 } 104 func getBlue(x: Int, y: Int) -> CGFloat { 105 let pixelInfo = bytesPerRow * y + x * bytesPerPixel 106 let blue = CGFloat(pixelData[pixelInfo+2]) / CGFloat(255.0) 107 108 return blue 109 } 110 func getAlpha(x: Int, y: Int) -> CGFloat { 111 let pixelInfo = bytesPerRow * y + x * bytesPerPixel 112 let alpha = CGFloat(pixelData[pixelInfo+3]) / CGFloat(255.0) 113 return alpha 114 } 115} 116 117 118struct ContentView: View { 119 120 @State var bin = 50.0 121 122 @State var isEditing = false 123 124 @State var img = UIImage(named: "Lena") 125 @State var img_bin :UIImage? 126 127 128 init() { 129 if let pixelBuffer = PixelBuffer(uiImage: img!) { 130 var r = [CGFloat]() 131 var g = [CGFloat]() 132 var b = [CGFloat]() 133 var a = [CGFloat]() 134 for x in 0..<pixelBuffer.width { 135 for y in 0..<pixelBuffer.height { 136 r.append(pixelBuffer.getRed(x: x, y: y)) 137 g.append(pixelBuffer.getGreen(x: x, y: y)) 138 b.append(pixelBuffer.getBlue(x: x, y: y)) 139 a.append(pixelBuffer.getAlpha(x: x, y: y)) 140 } 141 } 142 _img_bin = State(initialValue: img!.createBinarizedImage(r: r, g: g, b: b, a: a, threshold:bin)) 143 } else { 144 print("image not format") 145 } 146 } 147 148 var body: some View { 149 150 VStack{ 151 Image(uiImage:img!) 152 if let unwrap_img_bin = img_bin { 153 Image(uiImage:unwrap_img_bin) 154 } 155 else{ 156 Text("アンラップ失敗") 157 } 158 Slider( 159 value: $bin, 160 in: 0...100, 161 step: 1.0, 162 onEditingChanged: { 163 editing in 164 isEditing = editing 165 } 166 ) 167 168 Text("\(bin, specifier: "%.0f")") 169 .foregroundColor(isEditing ? .red : .blue) 170 171 } 172 } 173} 174 175 176struct ContentView_Previews: PreviewProvider { 177 static var previews: some View { 178 ContentView() 179 } 180} 181
試したこと
Lena以外の画像として、下記サイト様の"harumi"とLenaにアルファチャンネルを追加した画像は試してみましたが、同様の状況でした。
補足情報
こちらのサイト様を参考にさせていただいてます。
http://harumi.sakura.ne.jp/wordpress/2019/05/31/%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB%E5%A4%89%E6%8F%9B/
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。