Calculating the middle value of a canvas array in JavaScript in the most effective manner

My task involves working with an array of N HTMLCanvasElements that represent frames from a video. I aim to calculate the "median canvas" where every pixel's components (r, g, b, opacity) are the median values from all the canvases.

Each video frame is sized 1280x720, resulting in pixel data for each canvas (retrieved using

canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height).data
) being a Uint8ClampedArray with a length of 3,686,400.

The traditional method to find the median includes:

  • Create a result Uint8ClampedArray with a length of 3,686,400
  • Create a temporary Uint8ClampedArray with a length equal to N
  • Loop through 0 to 3,686,399
    • a) Iterate over the N canvases to populate the array
    • b) Calculate the median of the array
    • c) Store the median in the result array

This approach is sluggish, especially when dealing with just 4 canvases.

I am looking for a more efficient method or existing code to achieve this. While my question is similar to Find median of list of images, I specifically need a solution in JavaScript, not Python.

Note: For step b), I am using d3.median(). However, it doesn't support typed arrays, so conversion to numbers and then back to Uint8Clamped type becomes necessary.

Note 2: Although I lack expertise in GLSL shaders, perhaps exploring GPU utilization could lead to quicker results. This approach may involve transferring data from CPU to GPU, which might incur time if done frequently.

Note 3: The basic solution can be found here:

Answer №1

Your statement

Using d3.median() can be problematic with typed arrays...

While this may have been the assumption, it's not entirely accurate. The d3.median() function internally relies on the d3.quantile() method which starts by utilizing:

export default function quantile(values, p, valueof) {
  values = Float64Array.from(numbers(values, valueof));

The use of a Float64Array in this context is crucial for precise calculations. However, if your data is stored as integers in a Uint8ClampedArray, the frequent conversions to floating point values can significantly impact performance.

To address this issue, a custom function median(values) can be crafted based on d3.median() and d3.quantile():

function median(values) {
  // Avoid unnecessary conversion to floating point.
  if (!(n = values.length)) return;
  if (n < 2) return d3.min(values);
  var n,
      i = (n - 1) * 0.5,
      i0 = Math.floor(i),
      value0 = d3.max(d3.quickselect(values, i0).subarray(0, i0 + 1)),
      value1 = d3.min(values.subarray(i0 + 1));
  return value0 + (value1 - value0) * (i - i0);
}

This optimized version eliminates the need for immediate conversion and introduces enhancements tailored specifically for calculating the median value efficiently within a loop.

To implement this improvement, adjust your code as follows:

// Replace line below:
// medianImageData.data[i] = d3.median(arr);

// With:
medianImageData.data[i] = median(arr);

You can explore a functioning example in my modified version of your original Observable notebook.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Experiencing a problem with obtaining the .offset().top value of an element within an iframe resulting in an

Encountering an issue with Firefox and Safari where attempting to retrieve the .offset().top value from an element within an iframe results in undefined when trying to access this value. This functionality seems to be working properly in Chrome, Edge, and ...

Adding an array field to MongoDB documents using MongoClient in Node.js by referencing another field

I am managing a collection named Users. Here is an illustration of a document. {"_id":{"$oid":"xxxxxxxxxxxxxxxxxxx"}, "userId":"ANKIT", "token":"token123", "badge":{"$numberInt":"0"}, "useLocalCurrency":true, "notifyCustomerRejected":true, "notifyReworkR ...

Top method for utilizing render props in React

Currently, I am employing render model props. However, I have a hunch that there might be an alternative method to achieve the same outcome. Is anyone familiar with another approach? {variable === "nameComponen" && <component/>} {variable === "name ...

Delayed synchronization between CSS animation timing and JavaScript carousel interval causes a slight lag

I am currently working on a slider where one dot grows and another one follows suit. However, I have encountered a strange issue. I set the interval option to 2000ms for the slider and the CSS timing to 2000ms. div.bubble { height: 100px; border-ra ...

Expanding size on hover without affecting the alignment of surrounding elements

Imagine there are 10 divs on the page styled as squares, collectively known as the home page. Among these 10: 3 divs belong to the .event1 class, 5 divs belong to the .event2 class, and 2 divs belong to the .event3 class. <div class="boxes event1"> ...

Filtering content using a checkbox

I am trying to customize this code so that the displayed results show the values of all checkboxes selected. For example, if I check "computers" and "video-games," only result 3 should be shown. What steps should I take to implement this modification? &l ...

Inserting data into a JavaScript database

When attempting to add a new row to a datatable and submit it to a JSP for database insertion, an error is encountered. The error message reads: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the r ...

Using a for loop in JavaScript to dynamically display TextBoxFor(model=> model[i].prop) in an MVC application

I need some help getting this code to function correctly: $('#ddl').change(function () { $('#cont').html(''); var count = getCount($('#ddl').val()) for (var i = 0; i < count ; ...

Ways to determine the completion of the compilation process in Angular using the $compile service

Imagine having a popup directive that inherits a string template for the content it should display from the $scope. scope: { template: '=popInfo'//<div another directive></div> } This template string may even include another dire ...

Determine the frequency of keys and transform the data into an array of objects, with each object corresponding to a key and its frequency

Illustration of Frequency Count [ { language: 'JavaScript' },{ language: 'JavaScript' },{ language: 'TypeScript' }, ] CONVERSION TO = [ { language: 'JavaScript', count: 2 }, { language: 'C++', count: 1 ...

Step-by-step guide for properly transferring PHP MySQL data to ChartJs

I am looking to create bar charts and pie charts using ChartJs, with data fetched from php and mysql. Specifically, I want to generate a bar chart that illustrates the statistics of male and female students, along with the total number of students. The des ...

XMLHTTP is not accessible in the Department of Health

My D.O.H framework is powered by nodejs, specifically version 1.10. While I understand that nodejs typically uses xmlhttprequest or other modules for XHR requests, in my scenario, I am opting to utilize Dojo's xhr instead. Unfortunately, it seems tha ...

Exploring the ins and outs of HTML event handlers with JavaScript

When using events in your HTML and including a small amount of JavaScript, what is this called? Is it referred to as a "JavaScript attribute function," simply a "JavaScript attribute," or something else entirely? For example: <button onClick="locat ...

"Troubleshooting: Android - getSharedPreferences method not Resolving

Hello, I am facing an issue with getSharedPreferences not resolving. I have searched for solutions extensively but nothing seems to fix it. How can I implement getSharedPreferences in onclick inside ViewHolder? Here is the code snippet from MyHolder.class ...

Uncovering a hidden div tag in Listview ASP.NET with the power of Javascript

</p> <pre><code><ItemTemplate> <tr bgcolor="#efefef"> <td width="10%"> <asp:LinkButton ID="btnShowRoles" runat="server"> ...

The term "Require" is undefined. The Object.crypto and object.url

When attempting to upload a file from my React application, I encountered an error after installing aws-sdk. The error message is as follows: external "crypto":1 Uncaught ReferenceError: require is not defined at Object.crypto (external " ...

Leverage the power of Shopify API to retrieve a list of all products by making a request through

My website is custom built on node.js, and I am looking to retrieve all of my products in a single GET request. Unfortunately, the Shopify buy-button feature does not allow me to display all products at once due to pagination, hindering my ability to effec ...

Strategies for aligning the initial lines of text vertically within a table cell

I am faced with a unique challenge involving a table where the first cell contains the word "name" and the second cell contains some text. Sometimes, this text may include embedded images. The issue arises when an image appears on the first line of the tex ...

Tips for adding a scroll-to-top button on a page with only a vertical scroll bar

How can I make the scroll to top/bottom button only show up on pages with a vertical scrollbar? Currently, the button is not appearing when the page contains a vertical scrollbar. Any suggestions on how to implement this feature? ScrollToTopBottom.vue < ...

Manipulate and edit an array using JavaScript

Currently, I am working on a project in Javascript that involves processing a .dat file containing various data related to English Soccer teams. After extracting a Json from the file, I converted it into an array as follows: [{"team":"Arsena ...