Fix 29_FIX_FOCUS: semantic focus plane (person ID1+ID2 default), dedicated photoProcessExecutor prevents viewfinder freeze after shutter
This commit is contained in:
@@ -31,6 +31,8 @@ import java.nio.ByteBuffer
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
private lateinit var cameraExecutor: ExecutorService
|
||||
// Luồng xử lý ảnh độc lập - tránh chiếm dụng cameraExecutor gây freeze viewfinder
|
||||
private lateinit var photoProcessExecutor: ExecutorService
|
||||
|
||||
// Camera settings state
|
||||
private var lensFacing = CameraSelector.DEFAULT_FRONT_CAMERA // Default front camera
|
||||
@@ -136,6 +138,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
cameraExecutor = Executors.newSingleThreadExecutor()
|
||||
photoProcessExecutor = Executors.newSingleThreadExecutor()
|
||||
}
|
||||
|
||||
private fun initFrameData() {
|
||||
@@ -1381,19 +1384,18 @@ class MainActivity : AppCompatActivity() {
|
||||
val tempFile = java.io.File.createTempFile("raw_capture_", ".jpg", cacheDir)
|
||||
val outputOptions = ImageCapture.OutputFileOptions.Builder(tempFile).build()
|
||||
|
||||
// Dùng ContextCompat.getMainExecutor để callback nhanh, rồi chuyển xử lý nặng sang photoProcessExecutor
|
||||
imageCapture.takePicture(
|
||||
outputOptions,
|
||||
cameraExecutor,
|
||||
ContextCompat.getMainExecutor(this),
|
||||
object : ImageCapture.OnImageSavedCallback {
|
||||
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
||||
// Update gallery button thumbnail instantly
|
||||
// Update gallery button thumbnail instantly on UI thread
|
||||
try {
|
||||
val rawBitmap = android.graphics.BitmapFactory.decodeFile(tempFile.absolutePath)
|
||||
if (rawBitmap != null) {
|
||||
val thumb = android.graphics.Bitmap.createScaledBitmap(rawBitmap, 128, 128, true)
|
||||
runOnUiThread {
|
||||
binding.btnGalleryReview.setImageBitmap(thumb)
|
||||
}
|
||||
binding.btnGalleryReview.setImageBitmap(thumb)
|
||||
if (thumb != rawBitmap) {
|
||||
rawBitmap.recycle()
|
||||
}
|
||||
@@ -1402,14 +1404,15 @@ class MainActivity : AppCompatActivity() {
|
||||
// Ignore thumbnail decoding errors
|
||||
}
|
||||
|
||||
// Process and save in the background
|
||||
processAndSaveCapturedPhoto(tempFile)
|
||||
// ĐẨY TOÀN BỘ XỬ LÝ NẶNG (AI + LƯU ẢNH) SANG LUỒNG ĐỘC LẬP
|
||||
// cameraExecutor giờ rảnh hoàn toàn để tiếp tục chạy preview 60fps
|
||||
photoProcessExecutor.execute {
|
||||
processAndSaveCapturedPhoto(tempFile)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(exception: ImageCaptureException) {
|
||||
runOnUiThread {
|
||||
Toast.makeText(this@MainActivity, "Lỗi chụp ảnh: ${exception.message}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
Toast.makeText(this@MainActivity, "Lỗi chụp ảnh: ${exception.message}", Toast.LENGTH_SHORT).show()
|
||||
if (tempFile.exists()) {
|
||||
tempFile.delete()
|
||||
}
|
||||
@@ -1748,9 +1751,11 @@ class MainActivity : AppCompatActivity() {
|
||||
for (i in 0 until (w * h)) {
|
||||
val classId = if (i < bufferCapacity) rawBytes[i].toInt() else 0
|
||||
alphaMask[i] = if (focusClassId >= 0) {
|
||||
// Người dùng đã chạm chọn: chỉ lớp đúng class ID mới nét (Semantic Focus Plane)
|
||||
if (classId == focusClassId) 1.0f else 0.0f
|
||||
} else {
|
||||
if (classId in 1..5) 1.0f else 0.0f
|
||||
// Mặc định: Giữ nét toàn bộ Người (ID 1) và Phụ kiện cận cảnh (ID 2)
|
||||
if (classId == 1 || classId == 2) 1.0f else 0.0f
|
||||
}
|
||||
}
|
||||
blurAlphaMaskBox(alphaMask, w, h, radius = 3)
|
||||
@@ -1867,9 +1872,11 @@ class MainActivity : AppCompatActivity() {
|
||||
for (i in 0 until (w * h)) {
|
||||
val classId = if (i < bufferCapacity) categoryMaskBuffer.get(i).toInt() else 0
|
||||
alphaMask[i] = if (focusClassId >= 0) {
|
||||
// Người dùng đã chạm chọn: chỉ lớp đúng class ID mới nét (Semantic Focus Plane)
|
||||
if (classId == focusClassId) 1.0f else 0.0f
|
||||
} else {
|
||||
if (classId in 1..5) 1.0f else 0.0f
|
||||
// Mặc định: Giữ nét toàn bộ Người (ID 1) và Phụ kiện cận cảnh (ID 2)
|
||||
if (classId == 1 || classId == 2) 1.0f else 0.0f
|
||||
}
|
||||
}
|
||||
blurAlphaMaskBox(alphaMask, w, h, radius = 5)
|
||||
@@ -2154,6 +2161,7 @@ class MainActivity : AppCompatActivity() {
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
cameraExecutor.shutdown()
|
||||
photoProcessExecutor.shutdown()
|
||||
try {
|
||||
imageSegmenter?.close()
|
||||
} catch (e: Exception) {
|
||||
|
||||
Reference in New Issue
Block a user