当前位置: 首页 > news >正文

【IOS开发】SwiftUI + OpenCV实现图片的简单处理(一)

以下是在 Xcode 中使用 OpenCV 的完整 Demo,包含多个实用的图像处理功能:

1. 项目设置和安装

使用 CocoaPods 安装 OpenCV,在Profile文件中添加:

platform :ios, '12.0'
use_frameworks!target 'OpenCVDemo' dopod 'OpenCV'
end

然后运行:

pod install

项目架构

OpenCVDemo/
├── OpenCVDemo-Bridging-Header.h  
├── OpenCVDemoApp.swift
├── ContentView.swift
├── Tools/
│   ├── CVWrapper.h
│   ├── CVWrapper.mm
└── Resources/└── Assets.xcassets

2. 桥接头文件

Swift桥接OC,创建 Bridging-Header.h:

#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>

在项目设置中设置桥接文件路径:
Build Settings → Swift Compiler - General → Objective-C Bridging Header
在这里插入图片描述

3.Objective-C++ 包装器

创建 CVWrapper.h, 实现具体的方法:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN
@interface CVWrapper : NSObject
// 基础图像处理
+ (UIImage *)convertToGray:(UIImage *)image;
+ (UIImage *)detectEdges:(UIImage *)image;
+ (UIImage *)applyBlur:(UIImage *)image;
+ (UIImage *)applySharpen:(UIImage *)image;// 工具方法
+ (NSString *)openCVVersion;@endNS_ASSUME_NONNULL_END

创建 CVWrapper.mm:

#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
#import <opencv2/videoio/cap_ios.h>
#import <opencv2/objdetect.hpp>
#import "CVWrapper.h"using namespace cv;
using namespace std;@implementation CVWrapper
// MARK: - 基础图像处理+ (UIImage *)convertToGray:(UIImage *)image {Mat inputImage;UIImageToMat(image, inputImage);Mat grayImage;if (inputImage.channels() == 1) {grayImage = inputImage;} else {cvtColor(inputImage, grayImage, COLOR_BGR2GRAY);cvtColor(grayImage, grayImage, COLOR_GRAY2BGR); // 转回BGR用于UIImage显示}return MatToUIImage(grayImage);
}+ (UIImage *)detectEdges:(UIImage *)image {Mat inputImage;UIImageToMat(image, inputImage);Mat gray, edges;cvtColor(inputImage, gray, COLOR_BGR2GRAY);GaussianBlur(gray, gray, cv::Size(5, 5), 1.5);Canny(gray, edges, 50, 150);cvtColor(edges, edges, COLOR_GRAY2BGR);return MatToUIImage(edges);
}+ (UIImage *)applyBlur:(UIImage *)image {Mat inputImage;UIImageToMat(image, inputImage);Mat blurred;GaussianBlur(inputImage, blurred, cv::Size(15, 15), 0);return MatToUIImage(blurred);
}+ (UIImage *)applySharpen:(UIImage *)image {Mat inputImage;UIImageToMat(image, inputImage);Mat sharpened;Mat kernel = (Mat_<double>(3,3) <<0, -1,  0,-1,  5, -1,0, -1,  0);filter2D(inputImage, sharpened, -1, kernel);return MatToUIImage(sharpened);
}// MARK: - 工具方法+ (NSString *)openCVVersion {return [NSString stringWithFormat:@"OpenCV Version: %s", CV_VERSION];
}@end

4. 界面实现

//
//  ContentView.swift
//  OpenCVDemo
//import SwiftUIstruct ContentView: View {@State private var selectedTab = 0@State private var openCVVersion = ""var body: some View {TabView(selection: $selectedTab) {// 标签1: 图像处理ImageProcessingView().tabItem {Image(systemName: "photo")Text("图像处理")}.tag(0)// 标签4: 关于AboutView(openCVVersion: openCVVersion).tabItem {Image(systemName: "info.circle")Text("关于")}.tag(3)}.onAppear {openCVVersion = CVWrapper.openCVVersion()}}
}// MARK: - 图像处理视图
struct ImageProcessingView: View {@State private var originalImage: UIImage? = UIImage(named: "sample_image")@State private var processedImage: UIImage?@State private var selectedFilter = 0let filters = ["原始图像","灰度化","边缘检测","模糊处理","锐化处理",]var body: some View {NavigationView {VStack(spacing: 20) {// 图像显示区域HStack(spacing: 20) {VStack {Text("原图").font(.headline)if let image = originalImage {Image(uiImage: image).resizable().scaledToFit().frame(height: 200).border(Color.gray, width: 1)} else {RoundedRectangle(cornerRadius: 8).fill(Color.gray.opacity(0.3)).frame(height: 200).overlay(Text("请选择图片"))}}VStack {Text("处理后").font(.headline)if let image = processedImage {Image(uiImage: image).resizable().scaledToFit().frame(height: 200).border(Color.blue, width: 2)} else {RoundedRectangle(cornerRadius: 8).fill(Color.blue.opacity(0.3)).frame(height: 200).overlay(Text("处理结果"))}}}.padding()// 滤镜选择Picker("选择滤镜", selection: $selectedFilter) {ForEach(0..<filters.count, id: \.self) { index inText(filters[index]).tag(index)}}.pickerStyle(SegmentedPickerStyle()).padding(.horizontal)// 处理按钮Button("应用处理") {applyFilter()}.buttonStyle(.borderedProminent).disabled(originalImage == nil)// 图片选择Button("选择图片") {// 在实际应用中,这里应该使用UIImagePickerController// 为演示目的,我们使用内置的示例图片loadSampleImage()}.buttonStyle(.bordered)Spacer()}.navigationTitle("OpenCV 图像处理").padding()}}private func applyFilter() {guard let image = originalImage else { return }switch selectedFilter {case 1:processedImage = CVWrapper.convert(toGray: image)case 2:processedImage = CVWrapper.detectEdges(image)case 3:processedImage = CVWrapper.applyBlur(image)case 4:processedImage = CVWrapper.applySharpen(image)default:processedImage = image}}private func loadSampleImage() {// 在实际应用中,这里应该从相册或相机获取图片// 这里我们创建一个简单的示例图片let renderer = UIGraphicsImageRenderer(size: CGSize(width: 300, height: 300))let image = renderer.image { context inUIColor.blue.setFill()context.fill(CGRect(x: 0, y: 0, width: 300, height: 300))UIColor.red.setFill()context.fill(CGRect(x: 50, y: 50, width: 100, height: 100))UIColor.green.setFill()context.fill(CGRect(x: 150, y: 150, width: 100, height: 100))}originalImage = UIImage(named: "sample")processedImage = nil}
}// MARK: - 关于视图
struct AboutView: View {let openCVVersion: Stringvar body: some View {NavigationView {VStack(spacing: 20) {Image(systemName: "camera.filters").font(.system(size: 80)).foregroundColor(.blue)Text("OpenCV Swift Demo").font(.largeTitle).fontWeight(.bold)Text(openCVVersion).font(.title2).foregroundColor(.secondary)VStack(alignment: .leading, spacing: 15) {FeatureRow(icon: "photo", title: "图像处理", description: "灰度化、边缘检测、模糊、锐化")FeatureRow(icon: "camera", title: "实时处理", description: "相机实时OpenCV处理")FeatureRow(icon: "face.smiling", title: "人脸检测", description: "基于Haar级联的人脸检测")FeatureRow(icon: "square.and.arrow.down", title: "结果保存", description: "保存处理后的图片")}.padding()Spacer()Text("使用Swift和OpenCV构建").font(.caption).foregroundColor(.secondary)}.padding().navigationTitle("关于")}}
}struct FeatureRow: View {let icon: Stringlet title: Stringlet description: Stringvar body: some View {HStack {Image(systemName: icon).font(.title2).foregroundColor(.blue).frame(width: 40)VStack(alignment: .leading) {Text(title).font(.headline)Text(description).font(.caption).foregroundColor(.secondary)}Spacer()}}
}// MARK: - 预览
struct ContentView_Previews: PreviewProvider {static var previews: some View {ContentView()}
}

运行效果图

图片进行灰度处理

在这里插入图片描述

图片进行“边缘检测”处理

在这里插入图片描述

图片进行“模糊处理”

在这里插入图片描述

图像进行“锐化处理在这里插入图片描述

遇到的问题

1.问题一

Detected Apple 'NO' macro definition, it can cause build conflicts. Please, include this header before any Apple headers.
错误原因:
这个警告是因为OpenCV和Apple的SDK都定义了NO宏,导致冲突。OpenCV使用NO表示"Not OpenCV",而Apple的SDK使用NO作为布尔值。
解决办法:
调整头文件包含顺序,

// 先包含OpenCV头文件
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h>
#import <opencv2/videoio/cap_ios.h>// 然后包含Foundation
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
http://www.dtcms.com/a/528524.html

相关文章:

  • 【Docker】docker run
  • 成都网站建设 Vr便民网
  • LLama3架构原理浅浅学学
  • docker存储管理
  • Transformer架构发展历史
  • 【AI原生架构:数据架构】9、从打破数据孤岛到价值升维,企业数据资产变现全流程
  • Kubernetes 上的 GitLab + ArgoCD 实践(二):使用自建 GitLab Runner 完善 CI 流程
  • 网站如何查看浏览量2008建设网站
  • 开学季技术指南:高效知识梳理与实战经验分享
  • 网站推广计划渠道国外做美食视频网站有哪些
  • 金蝶K3老单 工艺路线维护特殊字符(使用模块返回值的方法)
  • 信贷控制范围
  • 乐陵网站优化最简单的网站设计
  • 项目信息和生产安全管理指南(试行)
  • 【Tesla】ICCV 2025技术分享
  • 企业做网站营销企业网站 响应式
  • 深度学习C++中的数据结构:栈和队列
  • 2025-tomcat web实践
  • 免费建立微信网站如何设计的英文网站
  • liferay 做网站哪里有网站开发公司
  • Leetcode 38
  • Django 学习路线图
  • 把网站放到服务器公司做网站需要准备什么资料
  • 如何批量获取蛋白质序列的所有结构域(domain)数据-2
  • MySQL基础知识大全
  • 站群服务器都有什么作用
  • C# 初级编程
  • linux fair调度器
  • 建设工程项目在哪个网站查询零食网站页面模板
  • Python 基础详解:enumerate() 函数