flutter - Null check operator used on a null value 오류 해결하기
ocr을 사용한 앱을 개발 중인데 갤러리에서 가져온 이미지는 ocr이 잘 적용하는데 카메라로 찍은 이미지는 ocr이 되지 않고 Null check operator used on a null value 이 오류가 자꾸 발생했다 ㅠㅠ
GPT , POE , 구글링 등등으로도 해결이 안 되다가 이번에 드디어 해결했다.
참고로 난 tesseractocr을 사용했고 이 오류 때문에 엄청 애먹었는데
이 글을 보고 조금이나마 도움이 됐으면 좋겠다
한 줄 요약 : 카메라로 찍은 사진이 갤러리에 저장되게 하고 여기서 이미지를 가져와 OCR 수행시킴
오류
먼저 오류가 나던 코드다
import 'package:flutter_tesseract_ocr/flutter_tesseract_ocr.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
//생략
//바텀바 부분
class BottomNavBar extends StatefulWidget {
const BottomNavBar({super.key});
@override
_BottomNavBarState createState() => _BottomNavBarState();
}
class _BottomNavBarState extends State<BottomNavBar> {
final ImagePicker _imagePicker = ImagePicker();
final _qrBarCodeScannerDialogPlugin = QrBarCodeScannerDialog();
String? code;
String parsedText = '';
late File? pickedImage;
late XFile? pickedFile;
late String img64;
//생략
@override
Widget build(BuildContext context) {
return BottomNavigationBar(
//생략
// 카메라 부분
Expanded(
child: ElevatedButton(
onPressed: () async {
Navigator.pop(context);
final pickedFile = await _imagePicker.pickImage(
source: ImageSource.camera,
);
if (pickedFile != null) {
var ocrText = await FlutterTesseractOcr.extractText(
pickedFile.path,
language: 'kor',
);
if (mounted) {
await Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => Information(
image: File(pickedFile.path),
parsedText: ocrText,
),
),
);
}
}
},
child: Text('Camera'),
),
),
// 갤러리 부분
Expanded(
child: ElevatedButton(
onPressed: () async {
final pickedFile = await _imagePicker.pickImage(
source: ImageSource.gallery);
if (pickedFile != null) {
// OCR 수행
var ocrText = await FlutterTesseractOcr.extractText(
pickedFile.path,
language: 'kor',
);
// Information 화면으로 이동하여 OCR 결과값 전달
await Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => Information(
image: File(pickedFile.path),
parsedText: ocrText,
),
),
);
}
},
child: Text('Gallery'),
),
),
//생략
나는 바텀바의 렌즈를 클릭하면 카메라, 갤러리, QR/바코드를 선택할 수 있는 버튼이 나오는데 여기의 카메라와 갤러리를 클릭하여 OCR이 적용되도록 하였다
OCR 결과는 Information이라는 화면으로 전환해서 보여지도록 함
밑의 코드는 OCR결과가 보여지는 Information화면의 코드이다
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_banergy/mypage/mypage.dart';
import 'package:flutter_tesseract_ocr/flutter_tesseract_ocr.dart';
class Information extends StatefulWidget {
final String imagePath;
const camerainformation({super.key, required this.imagePath});
@override
_InformationState createState() => _InformationState();
}
class InformationState extends State<Information> {
String parsedText = '';
bool isOcrInProgress = true;
@override
void initState() {
super.initState();
_performOCR();
}
void _performOCR() async {
try {
var ocrText = await FlutterTesseractOcr.extractText(
widget.imagePath,
language: 'kor',
);
setState(() {
parsedText = ocrText;
});
} finally {
setState(() {
isOcrInProgress = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('상품 정보'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const MypageApp()),
);
},
),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: SizedBox(
width: 150,
height: 150,
child: Image.file(File(widget.imagePath)),
),
),
const Divider(
color: Colors.grey,
thickness: 2.0,
height: 5.0,
),
const Center(
child: Text(
'OCR 결과',
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
),
),
),
if (isOcrInProgress)
const CircularProgressIndicator()
else
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(parsedText.isNotEmpty
? ' $parsedText'
: 'No text detected'),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context); // 현재 화면 닫기
},
child: const Text('닫기'),
),
],
),
),
);
}
}
해결
매번 문제를 못고치다가 문득 카메라로 찍은 사진이 갤러리에 저장이 안 된다는 사실을 알게 되었다.....
카메라로 찍은 사진/갤러리에서 가져오는 사진 둘 다 imagePicker를 통해 사진을 통해 사진을 가져오는데
카메라로 찍은 사진은 저장이 안되니 imagePicker을 통해 사진을 가져올 수 없어서 오류가 뜬다고 생각했다
그래서 갤러리 저장 함수인 saveImageToGallery를 사용해서 카메라로 찍은 이미지가 갤러리에 저장되도록 하였고
그 후 해당 이미지를 대상으로 OCR을 실행시킨 후 해당결과를 Information화면으로 전환되도록 하였다.
//카메라 부분 수정 및 추가된 부분
//사진을 찍은 후 갤러리에 저장
Future<void> _saveImageToGallery(
XFile pickedFile, BuildContext context) async {
final File imageFile = File(pickedFile.path);
try {
// OCR 수행
final String imagePath = await _performOCR(imageFile);
// 다음 화면으로 이동
if (mounted) {
final NavigatorState navigator = Navigator.of(context);
navigator.pushReplacement(
MaterialPageRoute(
builder: (BuildContext context) => camerainformation(
imagePath: imagePath,
),
),
);
}
} catch (e) {
print('OCR failed: $e');
// OCR 오류 시
}
}
//카메라 찍은 거
Future<String> _performOCR(File imageFile) async {
try {
return imageFile.path;
} catch (e) {
//오류 떴을때 확인
print('OCR failed: $e');
throw e;
}
}
//생략
Expanded(
child: ElevatedButton(
onPressed: () async {
final pickedFile = await _imagePicker.pickImage(
source: ImageSource.camera,
);
if (pickedFile != null) {
// OCR 수행
_saveImageToGallery(pickedFile, context);
}
},
child: const Text('Camera'),
),
),
그 결과.... 성공적으로 카메라로 찍은 사진이 갤러리에 저장되었고 OCR도 잘 작동하였다 ㅜㅜㅜ
https://github.com/kimnambin/banergy
GitHub - kimnambin/banergy
Contribute to kimnambin/banergy development by creating an account on GitHub.
github.com
이거에 대한 깃허브인데 필요하면 참고하기~~~