Skip to content

Commit

Permalink
Improve star detection
Browse files Browse the repository at this point in the history
Signed-off-by: Kyle Corry <kylecorry31@gmail.com>
  • Loading branch information
kylecorry31 committed Dec 25, 2024
1 parent 394a86d commit 8939093
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class CameraView(context: Context, attrs: AttributeSet?) : FrameLayout(context,
private var exposureTime: Duration? = null
private var sensitivity: Int? = null
private var focus: Float? = null
private var hasPendingChanges = false

var passThroughTouchEvents = false

Expand Down Expand Up @@ -125,6 +126,7 @@ class CameraView(context: Context, attrs: AttributeSet?) : FrameLayout(context,
isBackCamera = useBackCamera,
shouldStabilizePreview = shouldStabilizePreview
)
hasPendingChanges = true
camera?.start(this::onCameraUpdate)
}

Expand Down Expand Up @@ -157,6 +159,7 @@ class CameraView(context: Context, attrs: AttributeSet?) : FrameLayout(context,
isTorchOn = isOn
torchBtn.setImageResource(if (isOn) R.drawable.ic_torch_on else R.drawable.ic_torch_off)
camera?.setTorch(isTorchOn)
hasPendingChanges = true
}

fun setShowTorch(shouldShow: Boolean) {
Expand All @@ -170,6 +173,7 @@ class CameraView(context: Context, attrs: AttributeSet?) : FrameLayout(context,
val min = state?.ratioRange?.start ?: 1f
val max = state?.ratioRange?.end ?: 2f
camera?.setZoomRatio(SolMath.map(zoom, 0f, 1f, min, max))
hasPendingChanges = true
}

@Suppress("MemberVisibilityCanBePrivate")
Expand Down Expand Up @@ -204,18 +208,21 @@ class CameraView(context: Context, attrs: AttributeSet?) : FrameLayout(context,
}

camera?.setExposure(mapped)
hasPendingChanges = true
}

fun setManualExposure(exposureTime: Duration?, sensitivity: Int?) {
this.exposureTime = exposureTime
this.sensitivity = sensitivity
camera?.setExposureTime(exposureTime)
camera?.setSensitivity(sensitivity)
hasPendingChanges = true
}

fun setFocus(value: Float?) {
focus = value
camera?.setFocusDistancePercentage(value)
hasPendingChanges = true
}

fun setPreviewColorFilter(filter: ColorFilter?) {
Expand All @@ -235,11 +242,15 @@ class CameraView(context: Context, attrs: AttributeSet?) : FrameLayout(context,
if (zoom == -1f) {
setZoomRatio(1f)
}
setZoom(zoom)
setExposureCompensation(exposureCompensation)
setFocus(focus)
setManualExposure(exposureTime, sensitivity)
camera?.setTorch(isTorchOn)
if (hasPendingChanges) {
println("Applying changes")
setZoom(zoom)
setExposureCompensation(exposureCompensation)
setFocus(focus)
setManualExposure(exposureTime, sensitivity)
camera?.setTorch(isTorchOn)
hasPendingChanges = false
}
if (captureListener == null && imageListener == null) {
camera?.image?.close()
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import android.graphics.Bitmap
import com.kylecorry.andromeda.bitmaps.BitmapUtils.resizeToFit
import com.kylecorry.andromeda.core.units.PixelCoordinate

class ScaledStarFinder(private val finder: StarFinder, private val maxImageSize: Int): StarFinder {
class ScaledStarFinder(private val finder: StarFinder, private val maxImageSize: Int) : StarFinder {
override fun findStars(image: Bitmap): List<PixelCoordinate> {
val resized = image.resizeToFit(maxImageSize, maxImageSize)
val resized =
if (image.width <= maxImageSize && image.height <= maxImageSize) image else image.resizeToFit(
maxImageSize,
maxImageSize
)
val xScale = resized.width.toFloat() / image.width
val yScale = resized.height.toFloat() / image.height

Expand All @@ -15,7 +19,9 @@ class ScaledStarFinder(private val finder: StarFinder, private val maxImageSize:
PixelCoordinate(it.x / xScale, it.y / yScale)
}
} finally {
resized.recycle()
if (resized != image) {
resized.recycle()
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class StarFinderFactory {
mergeDistance = 5f
),
inPlace = true
), 1000
), 2000
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.kylecorry.trail_sense.tools.celestial_navigation.ui

import android.graphics.Bitmap
import android.graphics.Color
import android.os.Bundle
import android.util.Range
Expand All @@ -11,10 +12,13 @@ import androidx.camera.view.PreviewView
import com.kylecorry.andromeda.alerts.Alerts
import com.kylecorry.andromeda.alerts.toast
import com.kylecorry.andromeda.bitmaps.BitmapUtils.average
import com.kylecorry.andromeda.bitmaps.BitmapUtils.crop
import com.kylecorry.andromeda.bitmaps.BitmapUtils.resizeToFit
import com.kylecorry.andromeda.core.system.Resources
import com.kylecorry.andromeda.core.ui.Colors
import com.kylecorry.andromeda.core.ui.Colors.withAlpha
import com.kylecorry.andromeda.core.ui.setOnProgressChangeListener
import com.kylecorry.andromeda.core.units.PixelCoordinate
import com.kylecorry.andromeda.fragments.BoundFragment
import com.kylecorry.andromeda.fragments.inBackground
import com.kylecorry.andromeda.pickers.Pickers
Expand Down Expand Up @@ -80,6 +84,12 @@ class CelestialNavigationFragment : BoundFragment<FragmentCelestialNavigationBin
private val longExposure = LongExposure(10)
private var isAutoMode = false

private val imageLock = Any()
private var lastImage: Bitmap? = null
private var lastRotationMatrix: FloatArray? = null
private var lastInclination = 0f
private var lastAzimuth = 0f

private val exposureTimer = CoroutineTimer {
val image = onMain { binding.camera.previewImage } ?: return@CoroutineTimer
onDefault { longExposure.addFrame(image) }
Expand Down Expand Up @@ -140,8 +150,9 @@ class CelestialNavigationFragment : BoundFragment<FragmentCelestialNavigationBin
if (isAutoMode) {
binding.camera.setManualExposure(Duration.ofMillis(500), 3200)
} else {
binding.camera.setExposureCompensation(0.5f)
binding.exposureSlider.progress = 50
binding.camera.setManualExposure(Duration.ofMillis(250), 3200)
// binding.camera.setExposureCompensation(0.5f)
// binding.exposureSlider.progress = 50
}
binding.camera.setFocus(1f)
binding.arView.bind(binding.camera)
Expand Down Expand Up @@ -227,9 +238,18 @@ class CelestialNavigationFragment : BoundFragment<FragmentCelestialNavigationBin
super.onResume()
binding.arView.start(useGPS = false, customOrientationSensor = orientationSensor)
binding.camera.start(
readFrames = false,
shouldStabilizePreview = true
)
readFrames = true,
shouldStabilizePreview = false
) {
synchronized(imageLock) {
lastImage?.recycle()
lastImage = it
lastRotationMatrix = binding.arView.rotationMatrix.copyOf()
lastInclination = binding.arView.inclination
// TODO: Maybe set true north to false and calculate using a location suggested by the user
lastAzimuth = Bearing.getBearing(binding.arView.azimuth)
}
}
}

override fun onPause() {
Expand Down Expand Up @@ -329,21 +349,42 @@ class CelestialNavigationFragment : BoundFragment<FragmentCelestialNavigationBin
}

private fun recordStar() {
val rotationMatrix = binding.arView.rotationMatrix.copyOf()
var inclination = binding.arView.inclination
// TODO: Maybe set true north to false and calculate using a location suggested by the user
var azimuth = Bearing.getBearing(binding.arView.azimuth)
val image: Bitmap
val rotationMatrix: FloatArray
var azimuth: Float
var inclination: Float
val offsetX: Float
val offsetY: Float
val scaleX: Float
val scaleY: Float
synchronized(imageLock) {
// TODO: Calculate crop
val rect = binding.camera.camera?.getPreviewRect(false) ?: return
offsetX = rect.left
offsetY = rect.top
image = lastImage?.resizeToFit(2000, 2000) ?: return
scaleX = image.width.toFloat() / rect.width()
scaleY = image.height.toFloat() / rect.height()
rotationMatrix = lastRotationMatrix ?: return
azimuth = lastAzimuth
inclination = lastInclination
}


inBackground {
val job = launch {
if (!correctUsingCamera) {
return@launch
}

val image = binding.camera.previewImage
val brightness = image?.average()
val brightness = image.average()

if (image != null && brightness != null && brightness < 100) {
val starPixels = onDefault { starFinder.findStars(image) }
if (brightness < 100) {
val starPixels = onDefault {
starFinder.findStars(image).map {
PixelCoordinate(it.x / scaleX + offsetX, it.y / scaleY + offsetY)
}
}

if (isDebug()) {
val markers = starPixels.map {
Expand Down

0 comments on commit 8939093

Please sign in to comment.