<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vadim Volodin</title>
    <description>The latest articles on DEV Community by Vadim Volodin (@polyprogrammist).</description>
    <link>https://dev.to/polyprogrammist</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3713383%2F74875ed2-c669-45c3-b78a-3432fd292b48.jpg</url>
      <title>DEV Community: Vadim Volodin</title>
      <link>https://dev.to/polyprogrammist</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/polyprogrammist"/>
    <language>en</language>
    <item>
      <title>High-performance 3D vision - optimizing stereo block matching algorithm, part 1</title>
      <dc:creator>Vadim Volodin</dc:creator>
      <pubDate>Sat, 29 Aug 2026 15:24:47 +0000</pubDate>
      <link>https://dev.to/polyprogrammist/high-performance-3d-vision-optimizing-stereo-block-matching-algorithm-part-1-5gp4</link>
      <guid>https://dev.to/polyprogrammist/high-performance-3d-vision-optimizing-stereo-block-matching-algorithm-part-1-5gp4</guid>
      <description>&lt;p&gt;Hi! When I worked at Synopsys, I optimized algorithms for a specialized embedded vision processor — the kind used in autonomous driving and ADAS. In this post I'll cover how to optimize an algorithm that estimates the distance to objects from a pair of images. It's called Stereo Block Matching, and the prefix sums method is what makes it fast. Done naively, the same algorithm can run more than 100x slower.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stereo pair
&lt;/h2&gt;

&lt;p&gt;Let's look at an algorithm that estimates the distance from a camera to objects from a stereo pair. A stereo pair can be captured with two cameras pointed at the same spot, like a pair of eyes. It's two images — one from the left camera and one from the right. You can overlay them on top of each other and get a 3D movie. Here's what a stereo pair looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr2k43ymqg65dz58rh9dk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr2k43ymqg65dz58rh9dk.png" width="799" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An example of two images. One was taken by the left camera, the other by the right.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We'll represent the distances as a depth map. A depth map is an image whose pixel values encode the distance from the camera to the object visible at that pixel:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpeipxdjxu1jzv1lf1exb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpeipxdjxu1jzv1lf1exb.png" width="466" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A depth map built from a stereo pair&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's look at the principle behind recovering a depth map from a stereo pair. You can think of the stereo pair as two eyes. Human eyes are also able to judge distances to objects. Let's look at the diagram and try to picture how a person sees.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqcyxsfshpiwd0eww2riy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqcyxsfshpiwd0eww2riy.png" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Schematic view of a stereo pair. A1 — left camera. A2 — right camera. D — object. T — distance between the left and right cameras. Z — distance from the object to the camera plane. X0 — the intersection of the image plane with the line from the left camera to the object. (X0 − d) — the same for the right camera.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here we have point &lt;em&gt;D&lt;/em&gt; — the point whose distance we want to find. Point &lt;em&gt;A1&lt;/em&gt; is the left eye, &lt;em&gt;A2&lt;/em&gt; is the right one. For simplicity, imagine there's a pane of glass in front of our eyes with the image projected onto it. Point &lt;em&gt;X0&lt;/em&gt; is where the glass intersects the line from the left eye to the point, and point &lt;em&gt;X0 − d&lt;/em&gt; is where the glass intersects the line from the right eye to the point. Here &lt;em&gt;d&lt;/em&gt; is the shift of the object on the right image relative to the left one.&lt;/p&gt;

&lt;p&gt;We need to find the distance &lt;em&gt;Z&lt;/em&gt;. Let's apply the proportionality relation for the triangles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F49n41w3dlvpvjglkbjyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F49n41w3dlvpvjglkbjyr.png" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The sides and heights of the red and green triangles are proportional.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We get the following equation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhalidz7r8zz43xaz5tz5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhalidz7r8zz43xaz5tz5.png" width="799" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Solving for Z:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqtoxqpc9ewu8420bdldl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqtoxqpc9ewu8420bdldl.png" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem is that we somehow need to match what the left eye sees against what the right eye sees, so we can tell they're looking at the same point. In other words, we need to find the points &lt;em&gt;X0&lt;/em&gt; and &lt;em&gt;X0 − d&lt;/em&gt;. We'll assume these points lie at the same height. We know the focal length and the distance between the cameras. So the task boils down to this: for every pixel in the left image, find &lt;em&gt;d&lt;/em&gt; — how far that pixel is shifted in the right image.&lt;/p&gt;

&lt;p&gt;You can read more about stereo vision in &lt;a href="https://www.baeldung.com/cs/disparity-map-stereo-vision" rel="noopener noreferrer"&gt;this article&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Stereo Block Matching
&lt;/h2&gt;

&lt;p&gt;There are several algorithms for solving this problem, and one of them is Stereo Block Matching.&lt;/p&gt;

&lt;p&gt;It's based on the idea of finding similar neighborhoods around specific pixels. We'll consider the neighborhoods around two pixels as squares.&lt;/p&gt;

&lt;p&gt;For each pixel, we'll go over all possible shifts, compute the sum of squared differences between the left and right images, and pick the square with the smallest sum. The shift of that most-similar square (&lt;em&gt;d&lt;/em&gt;) reflects the relative distance to the object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0w53fq3w6caa3xciqal0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0w53fq3w6caa3xciqal0.png" width="799" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Pixel neighborhoods in the left- and right-camera images. The number is the light intensity at that pixel. As you can see, the intensities in this example are almost identical.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this example we can see the two squares don't differ much. To measure how similar they are, we build a new square holding the element-wise difference. The smaller that difference, the better.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv2fpvm4bwy3envmrtze4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv2fpvm4bwy3envmrtze4.png" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Element-wise difference of the pixel values&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once we have the square representing the difference between the two, we can sum up its elements:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;0 + 1 + 0 + 1 + 1 + 0 + 2 + 0 + 0 = 5&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a given pixel &lt;em&gt;X0&lt;/em&gt; in the left image, we iterate over different values of &lt;em&gt;d&lt;/em&gt;, which correspond to different pixels in the right image. We pick the &lt;em&gt;d&lt;/em&gt; that yields the minimum sum, and that will be the distance to the object.&lt;/p&gt;

&lt;p&gt;It's worth noting that besides the element-wise difference, there are many other cost functions. But we'll stick with this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naive solution
&lt;/h2&gt;

&lt;p&gt;In the naive solution we just do exactly what the algorithm describes, head-on. We go over every pixel in the left image, trying shifts from 0 up to some number, say 1000. For each pixel in the left image we walk over all the pixels in its neighborhood and, at the same time, walk over the pixels in the right image accounting for the shift. Then we sum up their differences. This is called the &lt;em&gt;SAD (Sum of Absolute Differences)&lt;/em&gt; metric:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft205cjy94kecjv628788.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft205cjy94kecjv628788.png" width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember that we can compute &lt;em&gt;d&lt;/em&gt; once we can compute &lt;em&gt;sad&lt;/em&gt; — for that we take the &lt;em&gt;d&lt;/em&gt; that minimizes &lt;em&gt;sad&lt;/em&gt;. And that &lt;em&gt;d&lt;/em&gt; is the distance to the object.&lt;/p&gt;

&lt;p&gt;So the formula for the distance to the object looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ficwh4v0ki2txqadsk7g5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ficwh4v0ki2txqadsk7g5.png" width="794" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The disparity for x, y is the d that minimizes sad(x, y, d)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's write out the algorithm. For simplicity our squares will be of size 3.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pseudocode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stereo_block_matching&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right_image&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="c1"&gt;# In the resulting image, pixel values encode the distance to the object
&lt;/span&gt;    &lt;span class="c1"&gt;# (the brighter, the closer)
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;best_disparity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
            &lt;span class="n"&gt;best_difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;disparity&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;shift_y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;shift_x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                        &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;right_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;shift_y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;shift_x&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;best_difference&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;best_difference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;best_difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt;
                    &lt;span class="n"&gt;best_disparity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;disparity&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;best_disparity&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's look at the complexity of this algorithm. Assuming the image is square with side &lt;em&gt;N&lt;/em&gt;, we search shifts from &lt;em&gt;0&lt;/em&gt; to &lt;em&gt;d&lt;/em&gt;, and the compared block is a square of size &lt;em&gt;K&lt;/em&gt;, the total complexity is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9m8our8k5pox0uenpm2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9m8our8k5pox0uenpm2e.png" width="800" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The prefix sums solution
&lt;/h2&gt;

&lt;p&gt;If &lt;em&gt;K&lt;/em&gt; equals 3, the complexity doesn't look too critical overall. But &lt;em&gt;K&lt;/em&gt; is usually larger, since a bigger neighborhood accounts for more pixels and gives higher accuracy. Of course, if you make &lt;em&gt;K&lt;/em&gt; too large, the algorithm gets less accurate again. A size of 21, for example, is commonly used. In that case &lt;em&gt;K × K&lt;/em&gt; is more than four hundred. If we could get rid of that &lt;em&gt;K × K&lt;/em&gt; factor in the asymptotics, we'd save a lot.&lt;/p&gt;

&lt;p&gt;The prefix sums method can help us here. The idea is to reuse a sum we've already computed. Right now we compute the sum of differences over a pixel neighborhood, then move on to compute it for the next shift and recompute it from scratch, even though we're only adding a new column and dropping an old one. Instead of recomputing the whole sum, we can recompute only the new and old columns. The idea is the same one used for a &lt;em&gt;box filter&lt;/em&gt;. The same thing happens when we move to the next row. We lose part of the already-computed sums; all we need is to add a new row and drop the old one, yet we recompute everything. But we can recompute just the new and old rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Column SAD&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now for a more detailed description. Let's introduce a variable &lt;em&gt;column_sad&lt;/em&gt; — the summed pixel difference over a portion of a column.&lt;/p&gt;

&lt;p&gt;Let's look at an example value of &lt;em&gt;column_sad[x, y]&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr253l54uljlpxqpo6e8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr253l54uljlpxqpo6e8e.png" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Computing column_sad: take the columns in the left and right images&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvugca7vkbj0lxdxzau9h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvugca7vkbj0lxdxzau9h.png" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Computing column_sad: the column of pixel differences between the left and right images&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this example &lt;em&gt;column_sad[x, y]&lt;/em&gt; equals &lt;em&gt;1 + 1 + 0 = 2.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The formula for &lt;em&gt;column_sad&lt;/em&gt; looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb1xfxm537jdgtwm3yofy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb1xfxm537jdgtwm3yofy.png" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The column_sad value&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Computing column_sad quickly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This variable can be recomputed in constant time using its value from the previous row.&lt;/p&gt;

&lt;p&gt;Here's an example of the fast update:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78u15dqoypzwn4kkn5ba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F78u15dqoypzwn4kkn5ba.png" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Add the element in the last row, subtract the one from the previous row&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F195vk8mgi4e64avikdts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F195vk8mgi4e64avikdts.png" width="696" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Add the difference in the last row, subtract it from the previous row&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this example &lt;em&gt;column_sad[x, y]&lt;/em&gt; equals &lt;em&gt;(1 + 1 + 0) + 8 − 1 = 9.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgsj2hdcpjut5qke8fvyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgsj2hdcpjut5qke8fvyq.png" width="799" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The same column_sad value, only computed faster&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Computing SAD from column_sad&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using &lt;em&gt;column_sad&lt;/em&gt; for a column, we can easily compute the SAD for the whole square:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhnevmh60rylixlavzfm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhnevmh60rylixlavzfm7.png" width="800" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, this sum can also be derived from the previous value:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuieokif355n1xhjd9j9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuieokif355n1xhjd9j9g.png" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's an example of the fast &lt;em&gt;SAD&lt;/em&gt; update:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp190gsxxzd8n5l6slzj2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp190gsxxzd8n5l6slzj2.png" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Add the last column, subtract the previous one&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqohjyh2z6unyyqjoa6d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqohjyh2z6unyyqjoa6d1.png" width="648" height="888"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Add the difference in the last column, subtract the difference in the previous column&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, &lt;em&gt;sad[x, y] = ((0 + 1 + 2) + (1 + 1 + 0) + (0 + 0 + 0)) + (3 + 2 + 4) − (0 + 1 + 2) = (1 + 1 + 0) + (0 + 0 + 0) + (3 + 2 + 4) = 2 + 0 + 9 = 11&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By first computing the &lt;em&gt;column_sad&lt;/em&gt; values for each y, and then, given those, computing &lt;em&gt;sad&lt;/em&gt; for the current pixel and shift, we get the following complexity:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmukidmqmmdt5f880mtp5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmukidmqmmdt5f880mtp5.png" width="800" height="65"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also notice that the &lt;em&gt;sad&lt;/em&gt; and &lt;em&gt;column_sad&lt;/em&gt; values for different shifts are independent of each other, so they can be computed separately and, accordingly, we only need to store &lt;em&gt;w&lt;/em&gt; memory for &lt;em&gt;column_sad&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The algorithm's code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stereo_block_matching&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right_image&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="c1"&gt;# In the resulting image, pixel values encode the distance to the object
&lt;/span&gt;    &lt;span class="c1"&gt;# (the brighter, the closer)
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="n"&gt;column_sad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[[]]]&lt;/span&gt;
    &lt;span class="n"&gt;sad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[[]]]&lt;/span&gt;
    &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block_size&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;best_disparity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
            &lt;span class="n"&gt;best_difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;sad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;column_sad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; \
                               &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;sad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; \
                               &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;column_sad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;column_sad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;right_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; \
                                      &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;column_sad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; \
                                      &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;right_image&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;best_difference&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;sad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;best_difference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;best_difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sad&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="n"&gt;best_disparity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;best_disparity&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's it. We've looked at applying the prefix sums method in a rather unusual role — estimating the distance from a camera to objects.&lt;/p&gt;

&lt;p&gt;In one of the next posts I'll show how to implement this algorithm even more efficiently on a processor that supports &lt;em&gt;SIMD&lt;/em&gt; and &lt;em&gt;VLIW&lt;/em&gt;, with a neat trick.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhd6hsy34o6pn3he4oby3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhd6hsy34o6pn3he4oby3.jpg" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>performance</category>
      <category>computervision</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Vadim Volodin</dc:creator>
      <pubDate>Thu, 15 Jan 2026 21:34:45 +0000</pubDate>
      <link>https://dev.to/polyprogrammist/-g8j</link>
      <guid>https://dev.to/polyprogrammist/-g8j</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/polyprogrammist" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3713383%2F74875ed2-c669-45c3-b78a-3432fd292b48.jpg" alt="polyprogrammist"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/polyprogrammist/integrating-ton-blockchain-into-trust-wallet-a-case-study-2fch" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Integrating TON blockchain into Trust Wallet: a case study&lt;/h2&gt;
      &lt;h3&gt;Vadim Volodin ・ Jan 15&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#blockchain&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#software&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cryptocurrency&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>blockchain</category>
      <category>opensource</category>
      <category>software</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>Integrating TON blockchain into Trust Wallet: a case study</title>
      <dc:creator>Vadim Volodin</dc:creator>
      <pubDate>Thu, 15 Jan 2026 20:56:22 +0000</pubDate>
      <link>https://dev.to/polyprogrammist/integrating-ton-blockchain-into-trust-wallet-a-case-study-2fch</link>
      <guid>https://dev.to/polyprogrammist/integrating-ton-blockchain-into-trust-wallet-a-case-study-2fch</guid>
      <description>&lt;p&gt;I had &lt;strong&gt;TON&lt;/strong&gt; cryptocurrency. I had &lt;strong&gt;Trust Wallet&lt;/strong&gt;. But I couldn't use them together — TON simply wasn't supported.&lt;/p&gt;

&lt;p&gt;I could have waited. Instead, I started building.&lt;/p&gt;

&lt;p&gt;A few months later, TON was live in a wallet with 130 million users.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Grant That Almost Fell Through
&lt;/h2&gt;

&lt;p&gt;I noticed that TON Foundation was offering &lt;strong&gt;development grants&lt;/strong&gt;. I applied. Almost immediately, they reached out — we hopped on a call and talked it through.&lt;/p&gt;

&lt;p&gt;At the same time, I messaged a friend who worked at Trust Wallet. Together, we set up a &lt;strong&gt;group chat&lt;/strong&gt;: Wallet Core developers, the TON team, my engineer friend, and me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then things got complicated.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Trust Wallet&lt;/em&gt; has &lt;strong&gt;two parts&lt;/strong&gt;. &lt;em&gt;Wallet Core&lt;/em&gt; is open-source and handles transaction signing. After discussing it in our chat, I realized we could contribute there. But there's a second part — app interaction (fetching balances, broadcasting transactions). That's &lt;strong&gt;closed-source&lt;/strong&gt;. Only Trust Wallet's internal team can build it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that means:&lt;/strong&gt; management approval, allocated engineering time, accountability. &lt;em&gt;Trust Wallet&lt;/em&gt; can't just say "sure, we'll ship it next month."&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TON Foundation&lt;/em&gt; had doubts: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if Trust Wallet never adds it to the app? Why fund the grant?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eventually, both teams &lt;strong&gt;met in the middle&lt;/strong&gt;. TON approved the grant; &lt;em&gt;Trust Wallet&lt;/em&gt; committed to prioritizing the integration. Win-win: a new blockchain and users for Trust Wallet, a new wallet and users for TON.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We started coding&lt;/strong&gt;. My friend did most of the development — I reviewed and refined. We merged the PR in about a month.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6uc8zjloe2rbfhwsv3o.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6uc8zjloe2rbfhwsv3o.jpg" alt="Integrating TON to Trust Wallet" width="640" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Trust Wallet Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;Trust Wallet runs on three platforms: Android, iOS, and a browser extension.&lt;/p&gt;

&lt;p&gt;At its core is &lt;strong&gt;Wallet Core&lt;/strong&gt; — an open-source library supporting &lt;strong&gt;over 130 blockchains&lt;/strong&gt;. Written in C++ and Rust. It's not just used by Trust Wallet; other major wallets like Crypto.com rely on it too. The library handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Private key generation&lt;/li&gt;
&lt;li&gt;Address creation and validation&lt;/li&gt;
&lt;li&gt;Transaction signing&lt;/li&gt;
&lt;li&gt;Smart contract interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where we added TON.&lt;/p&gt;




&lt;h2&gt;
  
  
  An Unexpected Bonus: Code from Everscale
&lt;/h2&gt;

&lt;p&gt;Few people know the full story.&lt;/p&gt;

&lt;p&gt;Originally, Durov launched TON, with &lt;em&gt;TON Labs&lt;/em&gt; handling part of the development. After US sanctions, Durov stepped away — but &lt;strong&gt;&lt;em&gt;TON Labs&lt;/em&gt;&lt;/strong&gt; didn't. They continued building a fork called &lt;em&gt;Free TON&lt;/em&gt;, which later became Everscale.&lt;/p&gt;

&lt;p&gt;Then a new &lt;strong&gt;&lt;em&gt;TON Foundation&lt;/em&gt;&lt;/strong&gt; emerged, endorsed by Durov. It's now integrated into Telegram and has taken off, becoming a leading TON blockchain.&lt;/p&gt;

&lt;p&gt;Here's the thing: &lt;em&gt;TON Labs&lt;/em&gt; did a lot of impressive technical work. Everscale was already in Wallet Core. We extracted the shared code into a module called &lt;strong&gt;CommonTON&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That code now powers both &lt;em&gt;Everscale&lt;/em&gt; and &lt;em&gt;TON&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes TON Unique
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Your Wallet Is a Smart Contract
&lt;/h3&gt;

&lt;p&gt;In TON, a wallet isn't just an address — it's a full-fledged smart contract. Everscale uses the older V3 wallet; for TON, we implemented V4R2.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transaction Structure
&lt;/h3&gt;

&lt;p&gt;In order to create a transaction from wallet, you have to send a message to the wallet smart contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;External Message (from user to their contract)
├── header: sender's contract address
├── stateInit: code and data (first transaction only)
└── body:
    ├── signature: Ed25519 signature
    └── signing_message:
        ├── wallet_id, expire_at, seqno
        └── Internal Message (to recipient)
            ├── header: "send Y nanotons to address Z"
            └── body: transfer comment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I won't go too deep here. You can read more about the V4 wallet &lt;a href="https://docs.ton.org/standard/wallets/v4" rel="noopener noreferrer"&gt;in the docs&lt;/a&gt; — including the source code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cells and BOC — A Unique Data Model
&lt;/h3&gt;

&lt;p&gt;All data in TON is represented as a tree of cells (Bag of Cells). Each cell holds up to 1023 bits of data and up to 4 references to other cells.&lt;/p&gt;

&lt;p&gt;Here's how we create a cell with V4R2 wallet data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;Cell&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Ref&lt;/span&gt; &lt;span class="n"&gt;WalletV4R2&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;createDataCell&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;CellBuilder&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appendU32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                       &lt;span class="c1"&gt;// sequence_number&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appendU32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;walletId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;// wallet_id&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appendRaw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// public key&lt;/span&gt;
    &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;appendBitZero&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                   &lt;span class="c1"&gt;// "no plugins" flag&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;intoCell&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Total: 321 bits&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To build a transaction, you assemble these cells correctly: recipient address, amount, comment — all packed into a BOC. Luckily, the BOC serializer was already implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Address Formats
&lt;/h3&gt;

&lt;p&gt;Everscale only has raw addresses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0:4f6bbb5de550f01a5b73792ceca77d8c933ab396a1e300eb0ab5a5f49a430986
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TON also supports a user-friendly format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EQBPa7td5VDwGltzeSzsp32MkzqzlqHjAOsKtaX0mkMJhq_B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a base64 string that includes address type information and a checksum. The checksum helps catch typos in seed phrases.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Tonkeeper and Trust Wallet Are Incompatible
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Mnemonic Problem
&lt;/h3&gt;

&lt;p&gt;Standards rule the blockchain world. Much of what originated in Bitcoin is still used today. BIP39 (Bitcoin Improvement Proposal) describes how to derive a private key from a seed phrase. The formula: &lt;code&gt;seed = hash(mnemonic + salt)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By standard, salt = &lt;code&gt;"mnemonic" + password&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In TON, salt = &lt;code&gt;"TON default seed"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The result: &lt;strong&gt;the same seed phrase produces different keys&lt;/strong&gt; in Tonkeeper vs. Trust Wallet. You cannot transfer a wallet between them.&lt;/p&gt;

&lt;p&gt;This isn't unique to TON — the same issue exists with Waves, Qtum, and Polkadot (sr25519).&lt;/p&gt;

&lt;h3&gt;
  
  
  Checksum Validation
&lt;/h3&gt;

&lt;p&gt;Seed phrase checksums protect users from typos — enter a wrong word, and the wallet rejects the phrase instead of generating a wrong address (and losing your funds forever). BIP-39 embeds a &lt;strong&gt;4-bit checksum&lt;/strong&gt; in the last word. TON requires that &lt;strong&gt;hash of the phrase starts with a zero byte&lt;/strong&gt;. These incompatible methods are yet another reason Tonkeeper and Trust Wallet aren't interchangeable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond Wallet Core
&lt;/h3&gt;

&lt;p&gt;In addition to the Wallet Core implementation, we provided Trust Wallet's team with &lt;strong&gt;code examples&lt;/strong&gt;: how to fetch transaction data, query wallet state, and more. Also &lt;strong&gt;consulted&lt;/strong&gt; on app integration questions related to TON. Also added blockchain info and the logo to the &lt;a href="https://github.com/trustwallet/assets" rel="noopener noreferrer"&gt;assets repository&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;We connected the TON and Trust Wallet teams. My friend and I built the integration into Wallet Core. Later, Trust Wallet team integrated blockchain into the apps. The code now runs in Trust Wallet across all platforms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;January 2023&lt;/strong&gt; — the PR was merged into Wallet Core.&lt;/p&gt;

&lt;p&gt;Numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;130 million Trust Wallet users gained access to TON&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/trustwallet/wallet-core/pull/2813" rel="noopener noreferrer"&gt;TON in Wallet Core&lt;/a&gt; — main integration&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/trustwallet/wallet-core/pull/3331" rel="noopener noreferrer"&gt;Jettons (TON tokens)&lt;/a&gt; — added later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/ton-society/grants-and-bounties/issues/81" rel="noopener noreferrer"&gt;Grant&lt;/a&gt; for blockchain integration&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ton-society/grants-and-bounties/issues/255" rel="noopener noreferrer"&gt;Grant&lt;/a&gt; for adding Jettons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few months later, I added Jettons, then moved on to other projects for TON and NEAR. But that's a story for another time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Occasionally I share notes on development and more on &lt;a href="https://x.com/polyprogrammist" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;I would also like to say thank you to:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://x.com/hewigovens" rel="noopener noreferrer"&gt;Tao Xu&lt;/a&gt;, &lt;a href="https://x.com/mileriesime" rel="noopener noreferrer"&gt;Sztergbaum Roman&lt;/a&gt;, &lt;a href="https://github.com/optout21" rel="noopener noreferrer"&gt;optout&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/sergey-boyko-0791/" rel="noopener noreferrer"&gt;Sergei&lt;/a&gt;, &lt;a href="https://github.com/vcoolish" rel="noopener noreferrer"&gt;Viacheslav&lt;/a&gt; from Trust Wallet team - for organisation and code review&lt;br&gt;
&lt;a href="https://x.com/playittodeath" rel="noopener noreferrer"&gt;Kirill&lt;/a&gt; from TON Foundation - for helping me manage all of that, &lt;a href="//linkedin.com/in/narek-abovyan-25347418b?originalSubdomain=ae"&gt;Narek&lt;/a&gt; - for tech support from TON, &lt;a href="https://x.com/steveyun_ton" rel="noopener noreferrer"&gt;Steve Yun&lt;/a&gt; - for grant and support&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/vbushev/" rel="noopener noreferrer"&gt;Viacheslav&lt;/a&gt; - for implementing the main integration&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/milosvova/" rel="noopener noreferrer"&gt;Vladimir&lt;/a&gt; from Trust Wallet - for making it possible and for code review&lt;br&gt;
And to everyone, who contributed to this project&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>opensource</category>
      <category>software</category>
      <category>cryptocurrency</category>
    </item>
  </channel>
</rss>
