Anonymous
Уровень масштабирования экспо-камеры не работает должным образом.
Сообщение
Anonymous » 21 июн 2024, 00:41
Я использую рабочий процесс, основанный на реагировании (Android). Причина, по которой я использую простой рабочий процесс, заключается в том, что я хочу использовать некоторые выставочные функции, такие как выставочная камера, и хочу запустить какой-нибудь скрипт open-cv (сценарий openCV находится в собственном коде) для обработки изображений.Я думаю, что обнаружил проблему с выставочной камерой. Первоначальный масштаб камеры (экспо-камеры) при первой загрузке приложения сильно отличается от уровня масштабирования, который я установил. В приведенном ниже коде я установил масштабирование на 0,1, но когда я открыл камеру при первой загрузке приложения, камера увеличила масштаб слишком сильно. Но когда я обновляю уровень масштабирования камеры с 0,1 до 0,12 (0,12 — это произвольное значение, которое я выбрал от 0 до 1) во время работы приложения, из-за живого обновления уровень масштабирования камеры внезапно обновляется. точный уровень масштабирования, на который я его изменил. В этом случае масштаб камеры будет обновлен до 0,12, что приведет к уменьшению масштаба камеры из-за живого обновления, которое произошло, когда я изменил собственный код реакции во время работы приложения. Я не знаю, вызвана ли эта проблема библиотекой Expo-Camera или это просто проблема моего кода.
Я оставил здесь весь код приложения камеры, который использовал
camera.js:
Код: Выделить всё
import React, { useState, useEffect, useRef } from "react";
import {
View,
StyleSheet,
Text,
FlatList,
TouchableOpacity,
Dimensions,
Platform,
} from "react-native";
import { Alert, Modal, Pressable, Image } from 'react-native';
import { Camera } from "expo-camera";
import { CameraView, useCameraPermissions } from 'expo-camera';
import CategoryGridTile from "../components/CategoryGridTile";
import Category from "../models/category";
import Ionicons from 'react-native-vector-icons/Ionicons';
import { Slider, NativeBaseProvider, Badge } from "native-base";
import RTNMyPicker from 'rtn-my-picker/js/NativeMyPicker';
export const CATEGORIES = [
new Category(
"c1",
"Auto",
"#DEDBD1",
"https://cdn-icons-png.flaticon.com/512/2226/2226124.png"
),
new Category(
"c2",
"Microchip 1",
"#DECD9D",
"https://cdn-icons-png.flaticon.com/512/8382/8382828.png"
),
new Category(
"c3",
"Microchip 2",
"#DECD9D",
"https://cdn-icons-png.flaticon.com/512/8382/8382828.png"
),
new Category(
"c4",
"Microchip 3",
"#DEDBD1",
"https://cdn-icons-png.flaticon.com/512/2226/2226124.png"
),
];
const bulbColorMap = {"Green":"green", "RED":"red", "Blue":"blue", "No LED":"white"};
export default function CamaraWithOverlay({ navigation }) {
const [modalVisible, setModalVisible] = useState(false);
const [hasPermission, setHasPermission] = useState(null);
const [isCameraVisible, setIsCameraVisible] = useState(false);
const camera = React.useRef(null);
const [imagePadding, setImagePadding] = useState(0);
const [cameraRatio, setCameraRatio] = useState("4:3");
const { height, width } = Dimensions.get("window");
const screenRatio = height / width;
const [isRatioSet, setIsRatioSet] = useState(false);
const [isTakingPhotos, setIsTakingPhotos] = useState(false);
const intervalIdRef = useRef(null);
const [zoomEnd, setZoomEnd] = useState(0.5);
const [timer, setTimer] = useState(0);
const [uriImage, setUriImage] = useState('');
const [standardImage, setStandardImage] = useState('');
const [currentImage, setCurrentImage] = useState('');
const [IsCameraAligned, setIsCameraAligned] = useState(false);
const [bulbColor, setBulbColor] = useState("white");
const [isCameraReady, setIsCameraReady] = useState(false);
useEffect(() => {
async function getCameraStatus() {
const { status } = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === "granted");
}
getCameraStatus();
}, []);
const prepareRatio = async () => {
let desiredRatio = "4:3";
if (Platform.OS === "android") {
const ratios = await camera.getSupportedRatiosAsync();
let distances = {};
let realRatios = {};
let minDistance = null;
for (const ratio of ratios) {
const parts = ratio.split(":");
const realRatio = parseInt(parts[0]) / parseInt(parts[1]);
realRatios[ratio] = realRatio;
const distance = screenRatio - realRatio;
distances[ratio] = distance;
if (minDistance == null) {
minDistance = ratio;
} else {
if (distance >= 0 && distance < distances[minDistance]) {
minDistance = ratio;
}
}
}
desiredRatio = minDistance;
const remainder = Math.floor(
(height - realRatios[desiredRatio] * width) / 2
);
setImagePadding(remainder);
setCameraRatio(desiredRatio);
setIsRatioSet(true);
}
};
const setCameraReady = async () => {
if (!isRatioSet) {
await prepareRatio();
}
setIsCameraReady(true);
};
useEffect(() => {
if (isCameraVisible) {
navigation.setOptions({
headerShown: false,
tabBarStyle: { display: "none" },
});
} else {
navigation.setOptions({
headerShown: true,
tabBarStyle: undefined,
});
}
}, [isCameraVisible]);
const checkImageAdjustment = async () => {
if (camera) {
try {
const photo = await camera.current.takePictureAsync({
base64: true,
});
if (photo) {
console.log("Photo1", photo.base64.slice(0, 60));
const result2 = await RTNMyPicker?.checkImageAdjustment2(photo.base64);
if(result2.processedImage){
console.log('Photo2', result2.processedImage.slice(0,60))
setUriImage(`data:image/png;base64,${result2.processedImage}`);
// setUriImage(`data:image/png;base64,${photo.base64}`);
setStandardImage(result2.processedImage)
}
result2.processedImage=""
console.log(result2)
// setUriImage(`data:image/png;base64,${photo.base64}`);
setModalVisible(true);
}
} catch (error) {
console.error("Error taking photo", error);
}
}
};
useEffect(() => {
let interval;
const fetchBulbColor = async () => {
if (currentImage !== "" && standardImage !== "" && IsCameraAligned) {
const result = await RTNMyPicker?.detectLEDs(
currentImage,
standardImage,
1.2
);
setBulbColor(result);
}
};
if (IsCameraAligned) {
interval = setInterval(async () => {
if (camera.current) {
const photo = await camera.current.takePictureAsync({
base64: true,
});
setCurrentImage(photo.base64);
await fetchBulbColor();
}
}, 1000); // Run every 500ms
setTimeout(() => {
clearInterval(interval);
}, 5000); // Stop after 5 seconds
}
return () => {
if (interval) clearInterval(interval);
};
}, [standardImage, currentImage]);
const takePhoto = async () => {
if (camera) {
try {
const photo = await camera.current.takePictureAsync({
base64: true,
});
if (photo) {
console.log("Photo", photo.base64.slice(0, 40));
}
} catch (error) {
console.error("Error taking photo", error);
}
}
};
const startPhotoCaptureSequence = () => {
if (isTakingPhotos) {
console.log("Photo capture is already in progress.");
return;
}
setIsTakingPhotos(true);
setTimer(0);
takePhoto();
intervalIdRef.current = setInterval(() => {
takePhoto();
setTimer((prevTimer) => prevTimer + 1);
}, 1000);
setTimeout(() => {
if (intervalIdRef.current) {
clearInterval(intervalIdRef.current);
intervalIdRef.current = null;
}
setIsTakingPhotos(false);
console.log("Finished taking photos.");
}, 6000);
};
const stopPhotoCaptureSequence = () => {
if (intervalIdRef.current) {
clearInterval(intervalIdRef.current);
intervalIdRef.current = null;
setIsTakingPhotos(false);
console.log("Photo capture stopped.");
}
};
if (hasPermission === null) {
return ;
}
if (hasPermission === false) {
return No access to camera;
}
function renderCategoryItem(itemData) {
return (
setIsCameraVisible(true)}
/>
);
}
return (
{isCameraVisible ? (
setIsCameraVisible(false)}
>
Back
{/* {
setZoom(v);
}}
onChangeEnd={(v) => {
v && setZoomEnd(v);
}}
>
*/}
{isTakingPhotos && (
{`Timer: ${timer}s`}
)}
{IsCameraAligned ?
Proper Camera Alignment
:
Adjust Camera Alignment
}
{
Alert.alert('Modal has been closed.');
setModalVisible(!modalVisible);
}}>
{uriImage==='' ? : }
style={[styles.button, styles.buttonCorrect]}
onPress={() => {
setIsCameraAligned(true);
setModalVisible(!modalVisible);
}}>
✔
{
Alert.alert('Adjust the phone camera to proprly observe the microchip');
setIsCameraAligned(false);
setModalVisible(!modalVisible);
}}>
✘
) : (
item.id}
renderItem={renderCategoryItem}
numColumns={2}
/>
)}
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "black",
},
camera: {
...StyleSheet.absoluteFillObject,
// flex: 1,
},
slider: {
width: 300,
height: 40,
alignSelf: "center",
position: "absolute",
bottom: 120,
},
overlay: {
flex: 1,
backgroundColor: "transparent",
justifyContent: "center",
alignItems: "center",
},
backButton: {
position: "absolute",
top: 40,
left: 20,
backgroundColor: "rgba(0,0,0,0.6)",
padding: 10,
borderRadius: 20,
},
backButtonText: {
color: "white",
fontSize: 16,
},
circleMesh: {
width: 150,
height: 150,
borderRadius: 150,
borderWidth: 2,
borderColor: "white",
backgroundColor: "transparent",
justifyContent: "center",
alignItems: "center",
},
squareMesh: {
width: 35,
height: 35,
borderWidth: 2,
borderColor: "purple",
position: "absolute",
backgroundColor: "transparent",
},
topLeftSquare: {
top: 210,
left: -60,
},
bottomLeftSquare: {
bottom: 210,
left: -60,
},
bottomRightSquare: {
bottom: 210,
right: -60,
},
timerTextBelowButton: {
color: "#fff",
fontSize: 18,
position: "absolute",
bottom: 20,
alignSelf: "center",
},
buttonContainer: {
position: "absolute",
bottom: 45,
left: "50%",
transform: [{ translateX: -35 }],
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
},
captureButton: {
width: 70,
height: 70,
borderRadius: 35,
backgroundColor: "#ff4242",
justifyContent: "center",
alignItems: "center",
},
buttonContainer1: {
position: "absolute",
bottom: 130,
left: "50%",
transform: [{ translateX: -35 }],
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
},
captureButton1: {
width: 50,
height: 50,
borderRadius: 35,
backgroundColor: "rgba(0, 0, 0, 0.5)",
justifyContent: "center",
alignItems: "center",
},
smallButton: {
position: "absolute",
bottom: 55,
right: 40,
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: "rgba(230, 220, 243, 0.4)",
justifyContent: "center",
alignItems: "center",
},
centeredView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginTop: 22,
},
modalView: {
margin: 20,
backgroundColor: 'white',
borderRadius: 20,
padding: 35,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
image: {
marginBottom: 20,
},
options: {
flexDirection: 'row',
justifyContent: 'space-between',
width: '60%',
},
button: {
borderRadius: 20,
padding: 10,
elevation: 2,
marginHorizontal: 10,
},
buttonClose: {
backgroundColor: '#2196F3',
},
buttonCorrect: {
backgroundColor: 'green',
},
buttonIncorrect: {
backgroundColor: 'red',
},
textStyle: {
color: 'white',
fontWeight: 'bold',
textAlign: 'center',
fontSize: 18,
},
modalText: {
marginBottom: 15,
textAlign: 'center',
},
badgeContainer: {
top: 10,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingRight: 10, // or use marginLeft on the bulb itself
},
bulbStyle: {
marginLeft: 10, // Space between the badge and the bulb
},
});
Я пытаюсь заставить камеру в своем приложении иметь правильно определенный масштаб при начальной загрузке самого приложения (а не при изменении уровня масштабирования при обновлении).
Подробнее здесь:
https://stackoverflow.com/questions/786 ... g-properly
1718919713
Anonymous
Я использую рабочий процесс, основанный на реагировании (Android). Причина, по которой я использую простой рабочий процесс, заключается в том, что я хочу использовать некоторые выставочные функции, такие как выставочная камера, и хочу запустить какой-нибудь скрипт open-cv (сценарий openCV находится в собственном коде) для обработки изображений.Я думаю, что обнаружил проблему с выставочной камерой. Первоначальный масштаб камеры (экспо-камеры) при первой загрузке приложения сильно отличается от уровня масштабирования, который я установил. В приведенном ниже коде я установил масштабирование на 0,1, но когда я открыл камеру при первой загрузке приложения, камера увеличила масштаб слишком сильно. Но когда я обновляю уровень масштабирования камеры с 0,1 до 0,12 (0,12 — это произвольное значение, которое я выбрал от 0 до 1) во время работы приложения, из-за живого обновления уровень масштабирования камеры внезапно обновляется. точный уровень масштабирования, на который я его изменил. В этом случае масштаб камеры будет обновлен до 0,12, что приведет к уменьшению масштаба камеры из-за живого обновления, которое произошло, когда я изменил собственный код реакции во время работы приложения. Я не знаю, вызвана ли эта проблема библиотекой Expo-Camera или это просто проблема моего кода. [code] [/code] Я оставил здесь весь код приложения камеры, который использовал camera.js: [code]import React, { useState, useEffect, useRef } from "react"; import { View, StyleSheet, Text, FlatList, TouchableOpacity, Dimensions, Platform, } from "react-native"; import { Alert, Modal, Pressable, Image } from 'react-native'; import { Camera } from "expo-camera"; import { CameraView, useCameraPermissions } from 'expo-camera'; import CategoryGridTile from "../components/CategoryGridTile"; import Category from "../models/category"; import Ionicons from 'react-native-vector-icons/Ionicons'; import { Slider, NativeBaseProvider, Badge } from "native-base"; import RTNMyPicker from 'rtn-my-picker/js/NativeMyPicker'; export const CATEGORIES = [ new Category( "c1", "Auto", "#DEDBD1", "https://cdn-icons-png.flaticon.com/512/2226/2226124.png" ), new Category( "c2", "Microchip 1", "#DECD9D", "https://cdn-icons-png.flaticon.com/512/8382/8382828.png" ), new Category( "c3", "Microchip 2", "#DECD9D", "https://cdn-icons-png.flaticon.com/512/8382/8382828.png" ), new Category( "c4", "Microchip 3", "#DEDBD1", "https://cdn-icons-png.flaticon.com/512/2226/2226124.png" ), ]; const bulbColorMap = {"Green":"green", "RED":"red", "Blue":"blue", "No LED":"white"}; export default function CamaraWithOverlay({ navigation }) { const [modalVisible, setModalVisible] = useState(false); const [hasPermission, setHasPermission] = useState(null); const [isCameraVisible, setIsCameraVisible] = useState(false); const camera = React.useRef(null); const [imagePadding, setImagePadding] = useState(0); const [cameraRatio, setCameraRatio] = useState("4:3"); const { height, width } = Dimensions.get("window"); const screenRatio = height / width; const [isRatioSet, setIsRatioSet] = useState(false); const [isTakingPhotos, setIsTakingPhotos] = useState(false); const intervalIdRef = useRef(null); const [zoomEnd, setZoomEnd] = useState(0.5); const [timer, setTimer] = useState(0); const [uriImage, setUriImage] = useState(''); const [standardImage, setStandardImage] = useState(''); const [currentImage, setCurrentImage] = useState(''); const [IsCameraAligned, setIsCameraAligned] = useState(false); const [bulbColor, setBulbColor] = useState("white"); const [isCameraReady, setIsCameraReady] = useState(false); useEffect(() => { async function getCameraStatus() { const { status } = await Camera.requestCameraPermissionsAsync(); setHasPermission(status === "granted"); } getCameraStatus(); }, []); const prepareRatio = async () => { let desiredRatio = "4:3"; if (Platform.OS === "android") { const ratios = await camera.getSupportedRatiosAsync(); let distances = {}; let realRatios = {}; let minDistance = null; for (const ratio of ratios) { const parts = ratio.split(":"); const realRatio = parseInt(parts[0]) / parseInt(parts[1]); realRatios[ratio] = realRatio; const distance = screenRatio - realRatio; distances[ratio] = distance; if (minDistance == null) { minDistance = ratio; } else { if (distance >= 0 && distance < distances[minDistance]) { minDistance = ratio; } } } desiredRatio = minDistance; const remainder = Math.floor( (height - realRatios[desiredRatio] * width) / 2 ); setImagePadding(remainder); setCameraRatio(desiredRatio); setIsRatioSet(true); } }; const setCameraReady = async () => { if (!isRatioSet) { await prepareRatio(); } setIsCameraReady(true); }; useEffect(() => { if (isCameraVisible) { navigation.setOptions({ headerShown: false, tabBarStyle: { display: "none" }, }); } else { navigation.setOptions({ headerShown: true, tabBarStyle: undefined, }); } }, [isCameraVisible]); const checkImageAdjustment = async () => { if (camera) { try { const photo = await camera.current.takePictureAsync({ base64: true, }); if (photo) { console.log("Photo1", photo.base64.slice(0, 60)); const result2 = await RTNMyPicker?.checkImageAdjustment2(photo.base64); if(result2.processedImage){ console.log('Photo2', result2.processedImage.slice(0,60)) setUriImage(`data:image/png;base64,${result2.processedImage}`); // setUriImage(`data:image/png;base64,${photo.base64}`); setStandardImage(result2.processedImage) } result2.processedImage="" console.log(result2) // setUriImage(`data:image/png;base64,${photo.base64}`); setModalVisible(true); } } catch (error) { console.error("Error taking photo", error); } } }; useEffect(() => { let interval; const fetchBulbColor = async () => { if (currentImage !== "" && standardImage !== "" && IsCameraAligned) { const result = await RTNMyPicker?.detectLEDs( currentImage, standardImage, 1.2 ); setBulbColor(result); } }; if (IsCameraAligned) { interval = setInterval(async () => { if (camera.current) { const photo = await camera.current.takePictureAsync({ base64: true, }); setCurrentImage(photo.base64); await fetchBulbColor(); } }, 1000); // Run every 500ms setTimeout(() => { clearInterval(interval); }, 5000); // Stop after 5 seconds } return () => { if (interval) clearInterval(interval); }; }, [standardImage, currentImage]); const takePhoto = async () => { if (camera) { try { const photo = await camera.current.takePictureAsync({ base64: true, }); if (photo) { console.log("Photo", photo.base64.slice(0, 40)); } } catch (error) { console.error("Error taking photo", error); } } }; const startPhotoCaptureSequence = () => { if (isTakingPhotos) { console.log("Photo capture is already in progress."); return; } setIsTakingPhotos(true); setTimer(0); takePhoto(); intervalIdRef.current = setInterval(() => { takePhoto(); setTimer((prevTimer) => prevTimer + 1); }, 1000); setTimeout(() => { if (intervalIdRef.current) { clearInterval(intervalIdRef.current); intervalIdRef.current = null; } setIsTakingPhotos(false); console.log("Finished taking photos."); }, 6000); }; const stopPhotoCaptureSequence = () => { if (intervalIdRef.current) { clearInterval(intervalIdRef.current); intervalIdRef.current = null; setIsTakingPhotos(false); console.log("Photo capture stopped."); } }; if (hasPermission === null) { return ; } if (hasPermission === false) { return No access to camera; } function renderCategoryItem(itemData) { return ( setIsCameraVisible(true)} /> ); } return ( {isCameraVisible ? ( setIsCameraVisible(false)} > Back {/* { setZoom(v); }} onChangeEnd={(v) => { v && setZoomEnd(v); }} > */} {isTakingPhotos && ( {`Timer: ${timer}s`} )} {IsCameraAligned ? Proper Camera Alignment : Adjust Camera Alignment } { Alert.alert('Modal has been closed.'); setModalVisible(!modalVisible); }}> {uriImage==='' ? : } style={[styles.button, styles.buttonCorrect]} onPress={() => { setIsCameraAligned(true); setModalVisible(!modalVisible); }}> ✔ { Alert.alert('Adjust the phone camera to proprly observe the microchip'); setIsCameraAligned(false); setModalVisible(!modalVisible); }}> ✘ ) : ( item.id} renderItem={renderCategoryItem} numColumns={2} /> )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "black", }, camera: { ...StyleSheet.absoluteFillObject, // flex: 1, }, slider: { width: 300, height: 40, alignSelf: "center", position: "absolute", bottom: 120, }, overlay: { flex: 1, backgroundColor: "transparent", justifyContent: "center", alignItems: "center", }, backButton: { position: "absolute", top: 40, left: 20, backgroundColor: "rgba(0,0,0,0.6)", padding: 10, borderRadius: 20, }, backButtonText: { color: "white", fontSize: 16, }, circleMesh: { width: 150, height: 150, borderRadius: 150, borderWidth: 2, borderColor: "white", backgroundColor: "transparent", justifyContent: "center", alignItems: "center", }, squareMesh: { width: 35, height: 35, borderWidth: 2, borderColor: "purple", position: "absolute", backgroundColor: "transparent", }, topLeftSquare: { top: 210, left: -60, }, bottomLeftSquare: { bottom: 210, left: -60, }, bottomRightSquare: { bottom: 210, right: -60, }, timerTextBelowButton: { color: "#fff", fontSize: 18, position: "absolute", bottom: 20, alignSelf: "center", }, buttonContainer: { position: "absolute", bottom: 45, left: "50%", transform: [{ translateX: -35 }], flexDirection: "row", justifyContent: "center", alignItems: "center", }, captureButton: { width: 70, height: 70, borderRadius: 35, backgroundColor: "#ff4242", justifyContent: "center", alignItems: "center", }, buttonContainer1: { position: "absolute", bottom: 130, left: "50%", transform: [{ translateX: -35 }], flexDirection: "row", justifyContent: "center", alignItems: "center", }, captureButton1: { width: 50, height: 50, borderRadius: 35, backgroundColor: "rgba(0, 0, 0, 0.5)", justifyContent: "center", alignItems: "center", }, smallButton: { position: "absolute", bottom: 55, right: 40, width: 50, height: 50, borderRadius: 25, backgroundColor: "rgba(230, 220, 243, 0.4)", justifyContent: "center", alignItems: "center", }, centeredView: { flex: 1, justifyContent: 'center', alignItems: 'center', marginTop: 22, }, modalView: { margin: 20, backgroundColor: 'white', borderRadius: 20, padding: 35, alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.25, shadowRadius: 4, elevation: 5, }, image: { marginBottom: 20, }, options: { flexDirection: 'row', justifyContent: 'space-between', width: '60%', }, button: { borderRadius: 20, padding: 10, elevation: 2, marginHorizontal: 10, }, buttonClose: { backgroundColor: '#2196F3', }, buttonCorrect: { backgroundColor: 'green', }, buttonIncorrect: { backgroundColor: 'red', }, textStyle: { color: 'white', fontWeight: 'bold', textAlign: 'center', fontSize: 18, }, modalText: { marginBottom: 15, textAlign: 'center', }, badgeContainer: { top: 10, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingRight: 10, // or use marginLeft on the bulb itself }, bulbStyle: { marginLeft: 10, // Space between the badge and the bulb }, }); [/code] Я пытаюсь заставить камеру в своем приложении иметь правильно определенный масштаб при начальной загрузке самого приложения (а не при изменении уровня масштабирования при обновлении). Подробнее здесь: [url]https://stackoverflow.com/questions/78649693/expo-camera-zoom-level-is-not-working-properly[/url]