OpenGL: Попытка вызвать виртуальный метод 'void Android.opengl.glsurfaceView $ glthread.surfacecreated ()' на ссылке на ⇐ JAVA
OpenGL: Попытка вызвать виртуальный метод 'void Android.opengl.glsurfaceView $ glthread.surfacecreated ()' на ссылке на
public class AnalysisActivity extends AppCompatActivity {
private static final String TAG = "AnalysisActivity";
private OverlayImageView overlayImageView;
private Uri imageUri;
private OrtEnvironment ortEnvironment;
private OrtSession ortSession;
private Bitmap selectedBitmap;
private DeltaERenderer renderer;
private GLSurfaceView glSurfaceView;
private String selectedWineType = null;
float deltaE = 0.0f;
private float deltaEForRed = -1;
private float deltaEForRose = -1;
private float deltaEForWhite = -1;
public static final Map WINE_COLORS = new HashMap() {{
put("Red Wine", new float[]{11.0f, 5.0f, 6.0f});
put("Rose Wine", new float[]{225.0f, 123.0f, 81.0f});
put("White Wine", new float[]{218.0f, 194.0f, 135.0f});
}};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_analysis);
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle("Analysis");
}
Button redWineButton = findViewById(R.id.redWineButton);
Button roseWineButton = findViewById(R.id.roseWineButton);
Button whiteWineButton = findViewById(R.id.whiteWineButton);
Button analyzeButton = findViewById(R.id.analyzeButton);
View.OnClickListener buttonClickListener = v -> {
if (v.isSelected()) {
v.setSelected(false);
selectedWineType = null;
//updateRenderer(null);
} else {
redWineButton.setSelected(false);
roseWineButton.setSelected(false);
whiteWineButton.setSelected(false);
v.setSelected(true);
selectedWineType = v == redWineButton ? "Red Wine" :
v == roseWineButton ? "Rose Wine" : "White Wine";
//updateRenderer(selectedWineType);
Toast.makeText(AnalysisActivity.this, "Selected: " + selectedWineType, Toast.LENGTH_SHORT).show();
}
};
redWineButton.setOnClickListener(buttonClickListener);
roseWineButton.setOnClickListener(buttonClickListener);
whiteWineButton.setOnClickListener(buttonClickListener);
overlayImageView = findViewById(R.id.selectedImageView);
glSurfaceView = findViewById(R.id.glSurfaceView);
glSurfaceView.setEGLContextClientVersion(3);
new Handler(Looper.getMainLooper()).postDelayed(() -> {
try {
showLoadingDialog();
initializeONNXModel();
initializeRenderer();
runInferenceAndRender();
onDeltaEValuesCalculated(new float[]{deltaEForRed, deltaEForRose, deltaEForWhite});
} catch (Exception e) {
e.printStackTrace();
} finally {
hideLoadingDialog();
}
}, 500);
analyzeButton.setOnClickListener(v -> {
new Thread(() -> {
try {
Pair result =
OnnxInference.runONNXModel(selectedBitmap, ortEnvironment, ortSession, this);
List detections = result.second;
runOnUiThread(() -> {
if (detections == null || detections.isEmpty()) {
Toast.makeText(this, "No detections found.", Toast.LENGTH_LONG).show();
} else {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
Intent intent = new Intent(AnalysisActivity.this, ResultActivity.class);
intent.putExtra("wineType", selectedWineType);
intent.putExtra("deltaEForWhite", deltaEForWhite);
intent.putExtra("deltaEForRose", deltaEForRose);
intent.putExtra("deltaEForRed", deltaEForRed);
intent.putExtra("deltaE", deltaE);
startActivity(intent);
}, 360);
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(() -> Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
}
}).start();
});
}
public void onDeltaEValuesCalculated(float[] deltaEValues) {
deltaEForWhite = deltaEValues[0];
deltaEForRose = deltaEValues[1];
deltaEForRed = deltaEValues[2];
deltaE = renderer.calculateDeltaE();
}
private void initializeONNXModel() {
try {
ortEnvironment = OrtEnvironment.getEnvironment();
ortSession = OnnxInference.loadModelFromAssets(ortEnvironment, this);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "Erro ao carregar o modelo ONNX.", Toast.LENGTH_LONG).show();
}
}
private void initializeRenderer() {
if (imageUri == null) {
Log.e(TAG, "Image URI is null, renderer cannot be initialized.");
return;
}
renderer = new DeltaERenderer(this, null, null, imageUri);
if (glSurfaceView != null) {
glSurfaceView.setRenderer(renderer);
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
} else {
Log.e(TAG, "GLSurfaceView is null, cannot set renderer.");
}
}
private void runInferenceAndRender() {
if (selectedBitmap == null || ortSession == null) {
Toast.makeText(this, "Erro: Imagem ou modelo não carregado.", Toast.LENGTH_LONG).show();
return;
}
// Run inference on a separate thread to avoid blocking the UI
new Thread(() -> {
try {
Pair result = OnnxInference.runONNXModel(selectedBitmap, ortEnvironment, ortSession,this);
runOnUiThread(() -> {
Bitmap outputBitmap = result.first;
List detections = result.second;
if (outputBitmap != null) {
overlayImageView.setImageBitmap(outputBitmap);
renderer.setDetections(detections);
if (glSurfaceView != null) {
// glSurfaceView.requestRender();
}
} else {
//Toast.makeText(this, "No detections found.", Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(() -> Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
}
}).start();
}
private void updateRenderer(String wineType) {
if (WINE_COLORS.containsKey(wineType)) {
selectedWineType = wineType;
float[] sampleRGB = WINE_COLORS.get(wineType);
Log.d(TAG, "Selected Wine Type: " + wineType);
Log.d(TAG, "Sample RGB: [" + sampleRGB[0] + ", " + sampleRGB[1] + ", " + sampleRGB[2] + "]");
renderer.setSampleRGB(sampleRGB);
glSurfaceView.requestRender();
} else {
Log.w(TAG, "Invalid Wine Type selected: " + wineType);
}
}
@Override
protected void onPause() {
super.onPause();
glSurfaceView.onPause();
}
@Override
protected void onResume() {
super.onResume();
new Handler(Looper.getMainLooper()).postDelayed(() -> {
glSurfaceView.onResume();
}, 500);
}
@Override
protected void onDestroy() {
super.onDestroy();
try {
if (ortSession != null) ortSession.close();
if (ortEnvironment != null) ortEnvironment.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
< /code>
Deltaerenderer Public Class Deltaerenderer реализует glsurfaceview.renderer {< /p>
private static final String TAG = "DeltaERenderer";
private Context context;
private int program;
private int textureId;
private int positionHandle;
private int texCoordHandle;
private int vbo;
private TextView analysisTextView;
private float deltaEValue;
private int framebuffer;
private int framebufferTexture;
private Uri imageUri;
private Bitmap bitmap;
private int imageWidth;
private int imageHeight;
private float[] sampleRGB;
public DeltaERenderer(Context context, TextView analysisTextView, float[] initialSampleRGB, Uri imageUri) {
this.context = context;
this.analysisTextView = analysisTextView;
this.sampleRGB = initialSampleRGB;
this.imageUri = imageUri;
}
public void setSampleRGB(float[] sampleRGB) {
this.sampleRGB = sampleRGB;
if (sampleRGB != null) {
Log.d(TAG, "Updated Sample RGB: [" + sampleRGB[0] + ", " + sampleRGB[1] + ", " + sampleRGB[2] + "]");
//glSurfaceView.requestRender();
} else {
Log.w(TAG, "Sample RGB is null. Ensure a wine type is selected.");
}
}
private List detections = new ArrayList();
public void setDetections(List detections) {
this.detections = detections;
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
Log.d(TAG, "onSurfaceCreated called");
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Load shaders
String vertexShaderCode = readShaderFromResource(R.raw.vertex_shader);
String fragmentShaderCode = readShaderFromResource(R.raw.fragment_shader);
int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode);
program = GLES30.glCreateProgram();
GLES30.glAttachShader(program, vertexShader);
GLES30.glAttachShader(program, fragmentShader);
GLES30.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
String error = GLES30.glGetProgramInfoLog(program);
GLES30.glDeleteProgram(program);
throw new RuntimeException("Program linking failed: " + error);
}
Log.d(TAG, "Shaders linked successfully");
try {
// Load the original image
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(imageUri));
if (bitmap == null) {
throw new RuntimeException("Failed to load image: bitmap is null.");
} else {
Log.d(TAG, "Image loaded successfully: width = " + bitmap.getWidth() + ", height = " + bitmap.getHeight());
}
// Recortar a região da bounding box
if (!detections.isEmpty()) {
OnnxInference.Detection detection = detections.get(0);
RectF box = detection.box;
// Calcular os limites inteiros da bounding box
int xMin = Math.max(0, (int) box.left);
int yMin = Math.max(0, (int) box.top);
int width = Math.min((int) (box.right - box.left), bitmap.getWidth() - xMin);
int height = Math.min((int) (box.bottom - box.top), bitmap.getHeight() - yMin);
// Recortar o bitmap
bitmap = Bitmap.createBitmap(bitmap, xMin, yMin, width, height);
}
} catch (IOException e) {
throw new RuntimeException("Failed to load image from URI: " + imageUri, e);
}
imageWidth = bitmap.getWidth();
imageHeight = bitmap.getHeight();
textureId = loadTexture(bitmap);
Log.d(TAG, "Texture loaded with ID: " + textureId);
if (textureId == 0) {
Log.e(TAG, "Failed to load texture.");
}
setupVertexBuffer();
setupFramebuffer();
}
private void setupVertexBuffer() {
float[] vertexData = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
int[] vboHandles = new int[1];
GLES30.glGenBuffers(1, vboHandles, 0);
vbo = vboHandles[0];
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertexData.length * 4,
java.nio.ByteBuffer.allocateDirect(vertexData.length * 4)
.order(java.nio.ByteOrder.nativeOrder())
.asFloatBuffer().put(vertexData).position(0),
GLES30.GL_STATIC_DRAW);
}
private void setupFramebuffer() {
int[] fbHandles = new int[1];
GLES30.glGenFramebuffers(1, fbHandles, 0);
framebuffer = fbHandles[0];
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, framebuffer);
int[] textureHandles = new int[1];
GLES30.glGenTextures(1, textureHandles, 0);
framebufferTexture = textureHandles[0];
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, framebufferTexture);
GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_R32F, imageWidth, imageHeight, 0, GLES30.GL_RED, GLES30.GL_FLOAT, null);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);
GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, framebufferTexture, 0);
int status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);
if (status != GLES30.GL_FRAMEBUFFER_COMPLETE) {
throw new RuntimeException("Framebuffer not complete: " + status);
}
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
}
@Override
public void onDrawFrame(GL10 gl10) {
long startTime = System.nanoTime();
// Bind the framebuffer to capture shader output
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, framebuffer);
GLES30.glViewport(0, 0, imageWidth, imageHeight);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
GLES30.glUseProgram(program);
// Set up the MVP matrix
float[] mvpMatrix = new float[16];
android.opengl.Matrix.setIdentityM(mvpMatrix, 0);
int mvpMatrixHandle = GLES30.glGetUniformLocation(program, "uMVPMatrix");
if (mvpMatrixHandle == -1) {
Log.e(TAG, "Could not get uniform location for uMVPMatrix");
return;
}
GLES30.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);
// Set texture
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
int textureHandle = GLES30.glGetUniformLocation(program, "uTexture");
if (textureHandle == -1) {
Log.e(TAG, "Could not get uniform location for uTexture");
return;
}
GLES30.glUniform1i(textureHandle, 0);
// Set vertex attributes
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo);
positionHandle = GLES30.glGetAttribLocation(program, "aPosition");
if (positionHandle == -1) {
Log.e(TAG, "Could not get attribute location for aPosition");
return;
}
GLES30.glEnableVertexAttribArray(positionHandle);
GLES30.glVertexAttribPointer(positionHandle, 3, GLES30.GL_FLOAT, false, 5 * 4, 0);
texCoordHandle = GLES30.glGetAttribLocation(program, "aTexCoord");
if (texCoordHandle == -1) {
Log.e(TAG, "Could not get attribute location for aTexCoord");
return;
}
GLES30.glEnableVertexAttribArray(texCoordHandle);
GLES30.glVertexAttribPointer(texCoordHandle, 2, GLES30.GL_FLOAT, false, 5 * 4, 3 * 4);
// Se sampleRGB for null, calcular Delta E para os três vinhos
float[] deltaEValues = new float[3];
if (sampleRGB == null) {
//Log.d(TAG, "Nenhum vinho selecionado, comparando com todos os tipos de vinho.");
int index = 0;
for (Map.Entry entry : WINE_COLORS.entrySet()) {
String wineType = entry.getKey();
float[] referenceRGB = entry.getValue();
int rgbHandle = GLES30.glGetUniformLocation(program, "uSampleRGB");
if (rgbHandle != -1) {
GLES30.glUniform3fv(rgbHandle, 1, referenceRGB, 0);
}
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
int numPixels = imageWidth * imageHeight;
float[] pixelArray = new float[numPixels];
GLES30.glReadPixels(0, 0, imageWidth, imageHeight, GLES30.GL_RED, GLES30.GL_FLOAT, FloatBuffer.wrap(pixelArray));
//Log.d(TAG, "DeltaE para " + wineType + ": " + Arrays.toString(pixelArray));
Arrays.sort(pixelArray);
if (numPixels % 2 == 0) {
deltaEValues[index] = (pixelArray[numPixels / 2 - 1] + pixelArray[numPixels / 2]) / 2.0f;
} else {
deltaEValues[index] = pixelArray[numPixels / 2];
}
//Log.d(TAG, "Delta E for " + wineType + ": " + deltaEValues[index]);
index++;
}
sendDeltaEValuesToAnalysis(deltaEValues);
} else {
// Se um vinho foi selecionado, calcula o Delta E apenas para ele
int rgbHandle = GLES30.glGetUniformLocation(program, "uSampleRGB");
if (rgbHandle != -1) {
GLES30.glUniform3fv(rgbHandle, 1, sampleRGB, 0);
}
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
int numPixels = imageWidth * imageHeight;
float[] pixelArray = new float[numPixels];
GLES30.glReadPixels(0, 0, imageWidth, imageHeight, GLES30.GL_RED, GLES30.GL_FLOAT, FloatBuffer.wrap(pixelArray));
//Log.d(TAG, "Valores de Delta E para vinho selecionado: " + Arrays.toString(pixelArray));
Arrays.sort(pixelArray);
float sum = 0;
for (float value : pixelArray) {
sum += value;
}
float mean = sum / numPixels;
// Calcular mediana
float median;
if (numPixels % 2 == 0) {
median = (pixelArray[numPixels / 2 - 1] + pixelArray[numPixels / 2]) / 2.0f;
} else {
median = pixelArray[numPixels / 2];
}
deltaEValue = median;
}
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1_000_000; // Convertendo de nanos para milissegundos
Log.d(TAG, "Tempo de cálculo do Delta E: " + duration + " ms");
// Unbind the framebuffer
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
}
private void sendDeltaEValuesToAnalysis(float[] deltaEValues) {
((AnalysisActivity) context).onDeltaEValuesCalculated(deltaEValues);
}
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
GLES30.glViewport(0, 0, width, height);
}
private int loadShader(int type, String shaderCode) {
int shader = GLES30.glCreateShader(type);
GLES30.glShaderSource(shader, shaderCode);
GLES30.glCompileShader(shader);
int[] compileStatus = new int[1];
GLES30.glGetShaderiv(shader, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
if (compileStatus[0] == 0) {
String error = GLES30.glGetShaderInfoLog(shader);
GLES30.glDeleteShader(shader);
Log.e(TAG, "Shader compilation failed: " + error);
throw new RuntimeException("Shader compilation failed: " + error);
}
return shader;
}
private String readShaderFromResource(int resourceId) {
InputStream inputStream = context.getResources().openRawResource(resourceId);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder shaderCode = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
shaderCode.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return shaderCode.toString();
}
private int loadTexture(Bitmap bitmap) {
final int[] textureHandle = new int[1];
GLES30.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0) {
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureHandle[0]);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
} else {
throw new RuntimeException("Error generating texture handle.");
}
return textureHandle[0];
}
public float calculateDeltaE() {
return deltaEValue;
}
< /code>
} < /p>
< /code>
`e Исключение Настройка поверхности
at android.opengl.glsurfaceview.surfacecreated (glsurfaceview.java:525)
at android.view.surfaceview.updatesurface (surfaceview.java:1240)
at android.view.surface.lambda. $ new $ 0 (surfaceview.java:231)
at android.view.surfaceview. $ r8 $ lambda $ nfzym_tg8f8lqzaovz7norefjzu (неизвестный источник: 0)
at android.view.surfaceView $$ Externalsynthetiticlambda1.onpredraw (d -veeffersynsynthetiticlambda1.onpredraw (d -view.surfaceview $$. $$ SyntheticClass: 0)
at android.view.viewtreeobserver.dispatchonpredraw (viewtreeobserver.java:1176)
at android.view.viewrootimpl.performtraversals (viewrootimpl.java:4239) .View.viewRootimpl.dotraversal (viewRootimpl.java:2917)
at android.view.viewrootimpl $ traversalrunnable.run (viewrootimpl.java:10324)
atroid.view.chorographer $ callbackRecord.run (chorerocrogr .java: 1406)
Я хочу инициализировать рендерер 500 мс после создания деятельности, но она дает эту ошибку
Подробнее здесь: https://stackoverflow.com/questions/794 ... ceviewglth
public class AnalysisActivity extends AppCompatActivity {
private static final String TAG = "AnalysisActivity";
private OverlayImageView overlayImageView;
private Uri imageUri;
private OrtEnvironment ortEnvironment;
private OrtSession ortSession;
private Bitmap selectedBitmap;
private DeltaERenderer renderer;
private GLSurfaceView glSurfaceView;
private String selectedWineType = null;
float deltaE = 0.0f;
private float deltaEForRed = -1;
private float deltaEForRose = -1;
private float deltaEForWhite = -1;
public static final Map WINE_COLORS = new HashMap() {{
put("Red Wine", new float[]{11.0f, 5.0f, 6.0f});
put("Rose Wine", new float[]{225.0f, 123.0f, 81.0f});
put("White Wine", new float[]{218.0f, 194.0f, 135.0f});
}};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_analysis);
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle("Analysis");
}
Button redWineButton = findViewById(R.id.redWineButton);
Button roseWineButton = findViewById(R.id.roseWineButton);
Button whiteWineButton = findViewById(R.id.whiteWineButton);
Button analyzeButton = findViewById(R.id.analyzeButton);
View.OnClickListener buttonClickListener = v -> {
if (v.isSelected()) {
v.setSelected(false);
selectedWineType = null;
//updateRenderer(null);
} else {
redWineButton.setSelected(false);
roseWineButton.setSelected(false);
whiteWineButton.setSelected(false);
v.setSelected(true);
selectedWineType = v == redWineButton ? "Red Wine" :
v == roseWineButton ? "Rose Wine" : "White Wine";
//updateRenderer(selectedWineType);
Toast.makeText(AnalysisActivity.this, "Selected: " + selectedWineType, Toast.LENGTH_SHORT).show();
}
};
redWineButton.setOnClickListener(buttonClickListener);
roseWineButton.setOnClickListener(buttonClickListener);
whiteWineButton.setOnClickListener(buttonClickListener);
overlayImageView = findViewById(R.id.selectedImageView);
glSurfaceView = findViewById(R.id.glSurfaceView);
glSurfaceView.setEGLContextClientVersion(3);
new Handler(Looper.getMainLooper()).postDelayed(() -> {
try {
showLoadingDialog();
initializeONNXModel();
initializeRenderer();
runInferenceAndRender();
onDeltaEValuesCalculated(new float[]{deltaEForRed, deltaEForRose, deltaEForWhite});
} catch (Exception e) {
e.printStackTrace();
} finally {
hideLoadingDialog();
}
}, 500);
analyzeButton.setOnClickListener(v -> {
new Thread(() -> {
try {
Pair result =
OnnxInference.runONNXModel(selectedBitmap, ortEnvironment, ortSession, this);
List detections = result.second;
runOnUiThread(() -> {
if (detections == null || detections.isEmpty()) {
Toast.makeText(this, "No detections found.", Toast.LENGTH_LONG).show();
} else {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
Intent intent = new Intent(AnalysisActivity.this, ResultActivity.class);
intent.putExtra("wineType", selectedWineType);
intent.putExtra("deltaEForWhite", deltaEForWhite);
intent.putExtra("deltaEForRose", deltaEForRose);
intent.putExtra("deltaEForRed", deltaEForRed);
intent.putExtra("deltaE", deltaE);
startActivity(intent);
}, 360);
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(() -> Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
}
}).start();
});
}
public void onDeltaEValuesCalculated(float[] deltaEValues) {
deltaEForWhite = deltaEValues[0];
deltaEForRose = deltaEValues[1];
deltaEForRed = deltaEValues[2];
deltaE = renderer.calculateDeltaE();
}
private void initializeONNXModel() {
try {
ortEnvironment = OrtEnvironment.getEnvironment();
ortSession = OnnxInference.loadModelFromAssets(ortEnvironment, this);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "Erro ao carregar o modelo ONNX.", Toast.LENGTH_LONG).show();
}
}
private void initializeRenderer() {
if (imageUri == null) {
Log.e(TAG, "Image URI is null, renderer cannot be initialized.");
return;
}
renderer = new DeltaERenderer(this, null, null, imageUri);
if (glSurfaceView != null) {
glSurfaceView.setRenderer(renderer);
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
} else {
Log.e(TAG, "GLSurfaceView is null, cannot set renderer.");
}
}
private void runInferenceAndRender() {
if (selectedBitmap == null || ortSession == null) {
Toast.makeText(this, "Erro: Imagem ou modelo não carregado.", Toast.LENGTH_LONG).show();
return;
}
// Run inference on a separate thread to avoid blocking the UI
new Thread(() -> {
try {
Pair result = OnnxInference.runONNXModel(selectedBitmap, ortEnvironment, ortSession,this);
runOnUiThread(() -> {
Bitmap outputBitmap = result.first;
List detections = result.second;
if (outputBitmap != null) {
overlayImageView.setImageBitmap(outputBitmap);
renderer.setDetections(detections);
if (glSurfaceView != null) {
// glSurfaceView.requestRender();
}
} else {
//Toast.makeText(this, "No detections found.", Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
e.printStackTrace();
runOnUiThread(() -> Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
}
}).start();
}
private void updateRenderer(String wineType) {
if (WINE_COLORS.containsKey(wineType)) {
selectedWineType = wineType;
float[] sampleRGB = WINE_COLORS.get(wineType);
Log.d(TAG, "Selected Wine Type: " + wineType);
Log.d(TAG, "Sample RGB: [" + sampleRGB[0] + ", " + sampleRGB[1] + ", " + sampleRGB[2] + "]");
renderer.setSampleRGB(sampleRGB);
glSurfaceView.requestRender();
} else {
Log.w(TAG, "Invalid Wine Type selected: " + wineType);
}
}
@Override
protected void onPause() {
super.onPause();
glSurfaceView.onPause();
}
@Override
protected void onResume() {
super.onResume();
new Handler(Looper.getMainLooper()).postDelayed(() -> {
glSurfaceView.onResume();
}, 500);
}
@Override
protected void onDestroy() {
super.onDestroy();
try {
if (ortSession != null) ortSession.close();
if (ortEnvironment != null) ortEnvironment.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
< /code>
Deltaerenderer Public Class Deltaerenderer реализует glsurfaceview.renderer {< /p>
private static final String TAG = "DeltaERenderer";
private Context context;
private int program;
private int textureId;
private int positionHandle;
private int texCoordHandle;
private int vbo;
private TextView analysisTextView;
private float deltaEValue;
private int framebuffer;
private int framebufferTexture;
private Uri imageUri;
private Bitmap bitmap;
private int imageWidth;
private int imageHeight;
private float[] sampleRGB;
public DeltaERenderer(Context context, TextView analysisTextView, float[] initialSampleRGB, Uri imageUri) {
this.context = context;
this.analysisTextView = analysisTextView;
this.sampleRGB = initialSampleRGB;
this.imageUri = imageUri;
}
public void setSampleRGB(float[] sampleRGB) {
this.sampleRGB = sampleRGB;
if (sampleRGB != null) {
Log.d(TAG, "Updated Sample RGB: [" + sampleRGB[0] + ", " + sampleRGB[1] + ", " + sampleRGB[2] + "]");
//glSurfaceView.requestRender();
} else {
Log.w(TAG, "Sample RGB is null. Ensure a wine type is selected.");
}
}
private List detections = new ArrayList();
public void setDetections(List detections) {
this.detections = detections;
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
Log.d(TAG, "onSurfaceCreated called");
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Load shaders
String vertexShaderCode = readShaderFromResource(R.raw.vertex_shader);
String fragmentShaderCode = readShaderFromResource(R.raw.fragment_shader);
int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode);
program = GLES30.glCreateProgram();
GLES30.glAttachShader(program, vertexShader);
GLES30.glAttachShader(program, fragmentShader);
GLES30.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES30.glGetProgramiv(program, GLES30.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
String error = GLES30.glGetProgramInfoLog(program);
GLES30.glDeleteProgram(program);
throw new RuntimeException("Program linking failed: " + error);
}
Log.d(TAG, "Shaders linked successfully");
try {
// Load the original image
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(imageUri));
if (bitmap == null) {
throw new RuntimeException("Failed to load image: bitmap is null.");
} else {
Log.d(TAG, "Image loaded successfully: width = " + bitmap.getWidth() + ", height = " + bitmap.getHeight());
}
// Recortar a região da bounding box
if (!detections.isEmpty()) {
OnnxInference.Detection detection = detections.get(0);
RectF box = detection.box;
// Calcular os limites inteiros da bounding box
int xMin = Math.max(0, (int) box.left);
int yMin = Math.max(0, (int) box.top);
int width = Math.min((int) (box.right - box.left), bitmap.getWidth() - xMin);
int height = Math.min((int) (box.bottom - box.top), bitmap.getHeight() - yMin);
// Recortar o bitmap
bitmap = Bitmap.createBitmap(bitmap, xMin, yMin, width, height);
}
} catch (IOException e) {
throw new RuntimeException("Failed to load image from URI: " + imageUri, e);
}
imageWidth = bitmap.getWidth();
imageHeight = bitmap.getHeight();
textureId = loadTexture(bitmap);
Log.d(TAG, "Texture loaded with ID: " + textureId);
if (textureId == 0) {
Log.e(TAG, "Failed to load texture.");
}
setupVertexBuffer();
setupFramebuffer();
}
private void setupVertexBuffer() {
float[] vertexData = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
int[] vboHandles = new int[1];
GLES30.glGenBuffers(1, vboHandles, 0);
vbo = vboHandles[0];
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertexData.length * 4,
java.nio.ByteBuffer.allocateDirect(vertexData.length * 4)
.order(java.nio.ByteOrder.nativeOrder())
.asFloatBuffer().put(vertexData).position(0),
GLES30.GL_STATIC_DRAW);
}
private void setupFramebuffer() {
int[] fbHandles = new int[1];
GLES30.glGenFramebuffers(1, fbHandles, 0);
framebuffer = fbHandles[0];
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, framebuffer);
int[] textureHandles = new int[1];
GLES30.glGenTextures(1, textureHandles, 0);
framebufferTexture = textureHandles[0];
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, framebufferTexture);
GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_R32F, imageWidth, imageHeight, 0, GLES30.GL_RED, GLES30.GL_FLOAT, null);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);
GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, framebufferTexture, 0);
int status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);
if (status != GLES30.GL_FRAMEBUFFER_COMPLETE) {
throw new RuntimeException("Framebuffer not complete: " + status);
}
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
}
@Override
public void onDrawFrame(GL10 gl10) {
long startTime = System.nanoTime();
// Bind the framebuffer to capture shader output
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, framebuffer);
GLES30.glViewport(0, 0, imageWidth, imageHeight);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
GLES30.glUseProgram(program);
// Set up the MVP matrix
float[] mvpMatrix = new float[16];
android.opengl.Matrix.setIdentityM(mvpMatrix, 0);
int mvpMatrixHandle = GLES30.glGetUniformLocation(program, "uMVPMatrix");
if (mvpMatrixHandle == -1) {
Log.e(TAG, "Could not get uniform location for uMVPMatrix");
return;
}
GLES30.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);
// Set texture
GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
int textureHandle = GLES30.glGetUniformLocation(program, "uTexture");
if (textureHandle == -1) {
Log.e(TAG, "Could not get uniform location for uTexture");
return;
}
GLES30.glUniform1i(textureHandle, 0);
// Set vertex attributes
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo);
positionHandle = GLES30.glGetAttribLocation(program, "aPosition");
if (positionHandle == -1) {
Log.e(TAG, "Could not get attribute location for aPosition");
return;
}
GLES30.glEnableVertexAttribArray(positionHandle);
GLES30.glVertexAttribPointer(positionHandle, 3, GLES30.GL_FLOAT, false, 5 * 4, 0);
texCoordHandle = GLES30.glGetAttribLocation(program, "aTexCoord");
if (texCoordHandle == -1) {
Log.e(TAG, "Could not get attribute location for aTexCoord");
return;
}
GLES30.glEnableVertexAttribArray(texCoordHandle);
GLES30.glVertexAttribPointer(texCoordHandle, 2, GLES30.GL_FLOAT, false, 5 * 4, 3 * 4);
// Se sampleRGB for null, calcular Delta E para os três vinhos
float[] deltaEValues = new float[3];
if (sampleRGB == null) {
//Log.d(TAG, "Nenhum vinho selecionado, comparando com todos os tipos de vinho.");
int index = 0;
for (Map.Entry entry : WINE_COLORS.entrySet()) {
String wineType = entry.getKey();
float[] referenceRGB = entry.getValue();
int rgbHandle = GLES30.glGetUniformLocation(program, "uSampleRGB");
if (rgbHandle != -1) {
GLES30.glUniform3fv(rgbHandle, 1, referenceRGB, 0);
}
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
int numPixels = imageWidth * imageHeight;
float[] pixelArray = new float[numPixels];
GLES30.glReadPixels(0, 0, imageWidth, imageHeight, GLES30.GL_RED, GLES30.GL_FLOAT, FloatBuffer.wrap(pixelArray));
//Log.d(TAG, "DeltaE para " + wineType + ": " + Arrays.toString(pixelArray));
Arrays.sort(pixelArray);
if (numPixels % 2 == 0) {
deltaEValues[index] = (pixelArray[numPixels / 2 - 1] + pixelArray[numPixels / 2]) / 2.0f;
} else {
deltaEValues[index] = pixelArray[numPixels / 2];
}
//Log.d(TAG, "Delta E for " + wineType + ": " + deltaEValues[index]);
index++;
}
sendDeltaEValuesToAnalysis(deltaEValues);
} else {
// Se um vinho foi selecionado, calcula o Delta E apenas para ele
int rgbHandle = GLES30.glGetUniformLocation(program, "uSampleRGB");
if (rgbHandle != -1) {
GLES30.glUniform3fv(rgbHandle, 1, sampleRGB, 0);
}
GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
int numPixels = imageWidth * imageHeight;
float[] pixelArray = new float[numPixels];
GLES30.glReadPixels(0, 0, imageWidth, imageHeight, GLES30.GL_RED, GLES30.GL_FLOAT, FloatBuffer.wrap(pixelArray));
//Log.d(TAG, "Valores de Delta E para vinho selecionado: " + Arrays.toString(pixelArray));
Arrays.sort(pixelArray);
float sum = 0;
for (float value : pixelArray) {
sum += value;
}
float mean = sum / numPixels;
// Calcular mediana
float median;
if (numPixels % 2 == 0) {
median = (pixelArray[numPixels / 2 - 1] + pixelArray[numPixels / 2]) / 2.0f;
} else {
median = pixelArray[numPixels / 2];
}
deltaEValue = median;
}
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1_000_000; // Convertendo de nanos para milissegundos
Log.d(TAG, "Tempo de cálculo do Delta E: " + duration + " ms");
// Unbind the framebuffer
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
}
private void sendDeltaEValuesToAnalysis(float[] deltaEValues) {
((AnalysisActivity) context).onDeltaEValuesCalculated(deltaEValues);
}
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
GLES30.glViewport(0, 0, width, height);
}
private int loadShader(int type, String shaderCode) {
int shader = GLES30.glCreateShader(type);
GLES30.glShaderSource(shader, shaderCode);
GLES30.glCompileShader(shader);
int[] compileStatus = new int[1];
GLES30.glGetShaderiv(shader, GLES30.GL_COMPILE_STATUS, compileStatus, 0);
if (compileStatus[0] == 0) {
String error = GLES30.glGetShaderInfoLog(shader);
GLES30.glDeleteShader(shader);
Log.e(TAG, "Shader compilation failed: " + error);
throw new RuntimeException("Shader compilation failed: " + error);
}
return shader;
}
private String readShaderFromResource(int resourceId) {
InputStream inputStream = context.getResources().openRawResource(resourceId);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder shaderCode = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
shaderCode.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return shaderCode.toString();
}
private int loadTexture(Bitmap bitmap) {
final int[] textureHandle = new int[1];
GLES30.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0) {
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureHandle[0]);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
} else {
throw new RuntimeException("Error generating texture handle.");
}
return textureHandle[0];
}
public float calculateDeltaE() {
return deltaEValue;
}
< /code>
} < /p>
< /code>
`e Исключение Настройка поверхности
at android.opengl.glsurfaceview.surfacecreated (glsurfaceview.java:525)
at android.view.surfaceview.updatesurface (surfaceview.java:1240)
at android.view.surface.lambda. $ new $ 0 (surfaceview.java:231)
at android.view.surfaceview. $ r8 $ lambda $ nfzym_tg8f8lqzaovz7norefjzu (неизвестный источник: 0)
at android.view.surfaceView $$ Externalsynthetiticlambda1.onpredraw (d -veeffersynsynthetiticlambda1.onpredraw (d -view.surfaceview $$. $$ SyntheticClass: 0)
at android.view.viewtreeobserver.dispatchonpredraw (viewtreeobserver.java:1176)
at android.view.viewrootimpl.performtraversals (viewrootimpl.java:4239) .View.viewRootimpl.dotraversal (viewRootimpl.java:2917)
at android.view.viewrootimpl $ traversalrunnable.run (viewrootimpl.java:10324)
atroid.view.chorographer $ callbackRecord.run (chorerocrogr .java: 1406)
Я хочу инициализировать рендерер 500 мс после создания деятельности, но она дает эту ошибку
Подробнее здесь: https://stackoverflow.com/questions/794 ... ceviewglth
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение