Swiftui 获取图像的显示尺寸
Swiftui getting an image's displaying dimensions
我正在尝试获取显示图像的尺寸,以便在我使用 Apple 的 Vision 框架识别的文本上绘制边界框。
所以我 运行 VNRecognizeTextRequest uppon 按下一个按钮与这个 funcion
func readImage(image:NSImage, completionHandler:@escaping(([VNRecognizedText]?,Error?)->()), comp:@escaping((Double?,Error?)->())) {
var recognizedTexts = [VNRecognizedText]()
var rr = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
let requestHandler = VNImageRequestHandler(cgImage: image.cgImage(forProposedRect: &rr, context: nil, hints: nil)!
, options: [:])
let textRequest = VNRecognizeTextRequest { (request, error) in
guard let observations = request.results as? [VNRecognizedTextObservation] else { completionHandler(nil,error)
return
}
for currentObservation in observations {
let topCandidate = currentObservation.topCandidates(1)
if let recognizedText = topCandidate.first {
recognizedTexts.append(recognizedText)
}
}
completionHandler(recognizedTexts,nil)
}
textRequest.recognitionLevel = .accurate
textRequest.recognitionLanguages = ["es"]
textRequest.usesLanguageCorrection = true
textRequest.progressHandler = {(request, value, error) in
comp(value,nil)
}
try? requestHandler.perform([textRequest])
}
并使用此结构和函数计算边界框偏移量
struct DisplayingRect:Identifiable {
var id = UUID()
var width:CGFloat = 0
var height:CGFloat = 0
var xAxis:CGFloat = 0
var yAxis:CGFloat = 0
init(width:CGFloat, height:CGFloat, xAxis:CGFloat, yAxis:CGFloat) {
self.width = width
self.height = height
self.xAxis = xAxis
self.yAxis = yAxis
}
}
func createBoundingBoxOffSet(recognizedTexts:[VNRecognizedText], image:NSImage) -> [DisplayingRect] {
var rects = [DisplayingRect]()
let imageSize = image.size
let imageTransform = CGAffineTransform.identity.scaledBy(x: imageSize.width, y: imageSize.height)
for obs in recognizedTexts {
let observationBounds = try? obs.boundingBox(for: obs.string.startIndex..<obs.string.endIndex)
let rectangle = observationBounds?.boundingBox.applying(imageTransform)
print("Rectange: \(rectangle!)")
let width = rectangle!.width
let height = rectangle!.height
let xAxis = rectangle!.origin.x - imageSize.width / 2 + rectangle!.width / 2
let yAxis = -(rectangle!.origin.y - imageSize.height / 2 + rectangle!.height / 2)
let rect = DisplayingRect(width: width, height: height, xAxis: xAxis, yAxis: yAxis)
rects.append(rect)
}
return(rects)
}
我使用此代码将矩形放置在 ContentView 中
ZStack{
Image(nsImage: self.img!)
.scaledToFit()
ForEach(self.rects) { rect in
Rectangle()
.fill(Color.init(.sRGB, red: 1, green: 0, blue: 0, opacity: 0.2))
.frame(width: rect.width, height: rect.height)
.offset(x: rect.xAxis, y: rect.yAxis)
}
}
如果我使用原始图像尺寸,我会得到这些结果
但是如果我添加
Image(nsImage: self.img!)
.resizable()
.scaledToFit()
我得到了这些结果
有没有办法获取图像尺寸并传递它们并获得显示图像的正确尺寸?我也需要这个,因为有时我无法显示整个图像并且需要缩放它。
非常感谢
Apple 没有将框架传递给每个视图,而是选择为您提供一个单独的 GeometryReader 视图,该视图将其框架作为参数传递给其子闭包。
struct Example: View {
var body: some View {
GeometryReader { geometry in
Image(systemName: "check")
.onAppear {
print(geometry.frame(in: .local))
}
}
}
}
我会在背景上使用 GeometryReader
,这样它会准确读取图像的大小,如下所示
@State var imageSize: CGSize = .zero // << or initial from NSImage
...
Image(nsImage: self.img!)
.resizable()
.scaledToFit()
.background(rectReader())
// ... somewhere below
private func rectReader() -> some View {
return GeometryReader { (geometry) -> AnyView in
let imageSize = geometry.size
DispatchQueue.main.async {
print(">> \(imageSize)") // use image actual size in your calculations
self.imageSize = imageSize
}
return AnyView(Rectangle().fill(Color.clear))
}
}
我正在尝试获取显示图像的尺寸,以便在我使用 Apple 的 Vision 框架识别的文本上绘制边界框。 所以我 运行 VNRecognizeTextRequest uppon 按下一个按钮与这个 funcion
func readImage(image:NSImage, completionHandler:@escaping(([VNRecognizedText]?,Error?)->()), comp:@escaping((Double?,Error?)->())) {
var recognizedTexts = [VNRecognizedText]()
var rr = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
let requestHandler = VNImageRequestHandler(cgImage: image.cgImage(forProposedRect: &rr, context: nil, hints: nil)!
, options: [:])
let textRequest = VNRecognizeTextRequest { (request, error) in
guard let observations = request.results as? [VNRecognizedTextObservation] else { completionHandler(nil,error)
return
}
for currentObservation in observations {
let topCandidate = currentObservation.topCandidates(1)
if let recognizedText = topCandidate.first {
recognizedTexts.append(recognizedText)
}
}
completionHandler(recognizedTexts,nil)
}
textRequest.recognitionLevel = .accurate
textRequest.recognitionLanguages = ["es"]
textRequest.usesLanguageCorrection = true
textRequest.progressHandler = {(request, value, error) in
comp(value,nil)
}
try? requestHandler.perform([textRequest])
}
并使用此结构和函数计算边界框偏移量
struct DisplayingRect:Identifiable {
var id = UUID()
var width:CGFloat = 0
var height:CGFloat = 0
var xAxis:CGFloat = 0
var yAxis:CGFloat = 0
init(width:CGFloat, height:CGFloat, xAxis:CGFloat, yAxis:CGFloat) {
self.width = width
self.height = height
self.xAxis = xAxis
self.yAxis = yAxis
}
}
func createBoundingBoxOffSet(recognizedTexts:[VNRecognizedText], image:NSImage) -> [DisplayingRect] {
var rects = [DisplayingRect]()
let imageSize = image.size
let imageTransform = CGAffineTransform.identity.scaledBy(x: imageSize.width, y: imageSize.height)
for obs in recognizedTexts {
let observationBounds = try? obs.boundingBox(for: obs.string.startIndex..<obs.string.endIndex)
let rectangle = observationBounds?.boundingBox.applying(imageTransform)
print("Rectange: \(rectangle!)")
let width = rectangle!.width
let height = rectangle!.height
let xAxis = rectangle!.origin.x - imageSize.width / 2 + rectangle!.width / 2
let yAxis = -(rectangle!.origin.y - imageSize.height / 2 + rectangle!.height / 2)
let rect = DisplayingRect(width: width, height: height, xAxis: xAxis, yAxis: yAxis)
rects.append(rect)
}
return(rects)
}
我使用此代码将矩形放置在 ContentView 中
ZStack{
Image(nsImage: self.img!)
.scaledToFit()
ForEach(self.rects) { rect in
Rectangle()
.fill(Color.init(.sRGB, red: 1, green: 0, blue: 0, opacity: 0.2))
.frame(width: rect.width, height: rect.height)
.offset(x: rect.xAxis, y: rect.yAxis)
}
}
如果我使用原始图像尺寸,我会得到这些结果
但是如果我添加
Image(nsImage: self.img!)
.resizable()
.scaledToFit()
我得到了这些结果
有没有办法获取图像尺寸并传递它们并获得显示图像的正确尺寸?我也需要这个,因为有时我无法显示整个图像并且需要缩放它。
非常感谢
Apple 没有将框架传递给每个视图,而是选择为您提供一个单独的 GeometryReader 视图,该视图将其框架作为参数传递给其子闭包。
struct Example: View {
var body: some View {
GeometryReader { geometry in
Image(systemName: "check")
.onAppear {
print(geometry.frame(in: .local))
}
}
}
}
我会在背景上使用 GeometryReader
,这样它会准确读取图像的大小,如下所示
@State var imageSize: CGSize = .zero // << or initial from NSImage
...
Image(nsImage: self.img!)
.resizable()
.scaledToFit()
.background(rectReader())
// ... somewhere below
private func rectReader() -> some View {
return GeometryReader { (geometry) -> AnyView in
let imageSize = geometry.size
DispatchQueue.main.async {
print(">> \(imageSize)") // use image actual size in your calculations
self.imageSize = imageSize
}
return AnyView(Rectangle().fill(Color.clear))
}
}