<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://boofcv.org/index.php?action=history&amp;feed=atom&amp;title=Example_Android_Fragment_Gradient</id>
	<title>Example Android Fragment Gradient - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://boofcv.org/index.php?action=history&amp;feed=atom&amp;title=Example_Android_Fragment_Gradient"/>
	<link rel="alternate" type="text/html" href="https://boofcv.org/index.php?title=Example_Android_Fragment_Gradient&amp;action=history"/>
	<updated>2026-05-08T05:30:45Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.36.2</generator>
	<entry>
		<id>https://boofcv.org/index.php?title=Example_Android_Fragment_Gradient&amp;diff=3263&amp;oldid=prev</id>
		<title>Peter: Created page with &quot;&lt;center&gt; &lt;gallery heights=300 widths=550 &gt; Image:Example_android_video.jpg| Colorized image gradient being displayed on an Android phone. &lt;/gallery&gt; &lt;/center&gt;  Demonstration o...&quot;</title>
		<link rel="alternate" type="text/html" href="https://boofcv.org/index.php?title=Example_Android_Fragment_Gradient&amp;diff=3263&amp;oldid=prev"/>
		<updated>2023-07-15T22:16:39Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&amp;lt;center&amp;gt; &amp;lt;gallery heights=300 widths=550 &amp;gt; Image:Example_android_video.jpg| Colorized image gradient being displayed on an Android phone. &amp;lt;/gallery&amp;gt; &amp;lt;/center&amp;gt;  Demonstration o...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery heights=300 widths=550 &amp;gt;&lt;br /&gt;
Image:Example_android_video.jpg| Colorized image gradient being displayed on an Android phone.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Demonstration of how to capture and process a video stream in real-time using BoofCV on an Android device as a [https://developer.android.com/guide/fragments Fragment]. Using Fragments as compared to the old style multi Activity projects in Android is a cleaner API and is the approach that you should use going forward. BoofCV provides ImageProcessingFragment and CameraProcessFragment. The former makes it easy to process and display the original image with visuals, while the other just provides a way to captures the video feed. The new BoofCV Android API is designed so that multiple video streams can be processed at once.&lt;br /&gt;
&lt;br /&gt;
Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0.44/integration/boofcv-android/examples/fragment/app/src/main/java/org/boofcv/android/example/EdgeFragment.kt EdgeFragment]&lt;br /&gt;
&lt;br /&gt;
Complete Project: [https://github.com/lessthanoptimal/BoofCV/tree/v0.44/integration/boofcv-android/examples/fragment Android Project]&lt;br /&gt;
&lt;br /&gt;
Concepts:&lt;br /&gt;
* Android&lt;br /&gt;
* Image Gradient&lt;br /&gt;
&lt;br /&gt;
Related Tutorial:&lt;br /&gt;
* [[Android_support| Android Support]]&lt;br /&gt;
&lt;br /&gt;
Related Examples:&lt;br /&gt;
* [[Example_Image_Filter| Image Filter]]&lt;br /&gt;
&lt;br /&gt;
= Example Code =&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Process a video feed, computes edges, displays a visualization of the edges.&lt;br /&gt;
 */&lt;br /&gt;
class EdgeFragment : ImageProcessingFragment() {&lt;br /&gt;
    // Bindings for user interface&lt;br /&gt;
    private var _uiBinding: EdgeLayoutBinding? = null&lt;br /&gt;
    private val uiBinding get() = _uiBinding!!&lt;br /&gt;
&lt;br /&gt;
    init {&lt;br /&gt;
        val derivX = GrayS16(0, 0)&lt;br /&gt;
        val derivY = GrayS16(0, 0)&lt;br /&gt;
        val gradientOp = FactoryDerivative.three(GrayU8::class.java, GrayS16::class.java)&lt;br /&gt;
&lt;br /&gt;
        imageProcessing = object : AndroidImageProcessing {&lt;br /&gt;
            // These are images that Android understands and used to visualization&lt;br /&gt;
            // A double buffer strategy is used to allow the processing and UI threads&lt;br /&gt;
            // to run with minimal coupling&lt;br /&gt;
            var bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)&lt;br /&gt;
            var bitmapWork = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)&lt;br /&gt;
            val bitmapTmp = DogArray_I8()&lt;br /&gt;
&lt;br /&gt;
            override fun process(frame: LockImages) {&lt;br /&gt;
                // Compute the gradient&lt;br /&gt;
                gradientOp.process(frame.gray, derivX, derivY)&lt;br /&gt;
&lt;br /&gt;
                // Make sure the bitmap is large enough&lt;br /&gt;
                bitmapWork = ConvertBitmap.checkDeclare(frame.gray, bitmapWork)&lt;br /&gt;
&lt;br /&gt;
                // Visualize the gradient&lt;br /&gt;
                VisualizeImageData.colorizeGradient(derivX, derivY, -1, bitmapWork, bitmapTmp);&lt;br /&gt;
&lt;br /&gt;
                // Visualization and image processing are two different threads.&lt;br /&gt;
                // To avoid reading / writing the same data structure at the same time we will&lt;br /&gt;
                // synchronize&lt;br /&gt;
                synchronized(this) {&lt;br /&gt;
                    // Perform a fast swap&lt;br /&gt;
                    val tmp = bitmapWork&lt;br /&gt;
                    bitmapWork = bitmap&lt;br /&gt;
                    bitmap = tmp&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            override fun visualize(canvas: Canvas, imageToView: Matrix) {&lt;br /&gt;
                // Draw the visualized gradient to the canvas&lt;br /&gt;
                synchronized(this) {&lt;br /&gt;
                    canvas.drawBitmap(this.bitmap, imageToView, null)&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    override fun onDestroyView() {&lt;br /&gt;
        _uiBinding = null&lt;br /&gt;
        super.onDestroyView()&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Need to tell it where it will render the results&lt;br /&gt;
     */&lt;br /&gt;
    override fun getCameraFrame(): FrameLayout {&lt;br /&gt;
        return uiBinding.cameraFrame&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    override fun onCreateView(&lt;br /&gt;
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?&lt;br /&gt;
    ): View {&lt;br /&gt;
        _uiBinding = EdgeLayoutBinding.inflate(inflater, container, false)&lt;br /&gt;
        return uiBinding.root&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    override fun lookupCameraConfig(selectedCam: CameraID, resolution: ImageDimension) {&lt;br /&gt;
        // Tell it to use the first camera that it finds that&amp;#039;s back facing. If none are found&lt;br /&gt;
        // then it will use a front facing camera&lt;br /&gt;
        val cameras = BoofAndroidUtils.getAllCameras(cameraManager)&lt;br /&gt;
        for (camera in cameras) {&lt;br /&gt;
            selectedCam.setTo(camera)&lt;br /&gt;
&lt;br /&gt;
            val characteristics = cameraManager.getCameraCharacteristics(camera.id)&lt;br /&gt;
            val facing = characteristics.get(CameraCharacteristics.LENS_FACING)&lt;br /&gt;
&lt;br /&gt;
            if (BoofAndroidUtils.facingToString(facing) == &amp;quot;back&amp;quot;) {&lt;br /&gt;
                break&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Hard code 640x480 If there isn&amp;#039;t an exact match it will select something close&lt;br /&gt;
        resolution.setTo(640, 480)&lt;br /&gt;
&lt;br /&gt;
        Log.i(TAG, &amp;quot;Selected camera $selectedCam&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    override fun customConfigure(cameraID: CameraID, builder: CaptureRequest.Builder) {&lt;br /&gt;
        // nothing special needs to be done so this function is empty&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Peter</name></author>
	</entry>
</feed>