# Content-aware image resizing in JavaScript
![Content-aware image resizing in JavaScript](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/01-cover-02.png)
> There is an [interactive version of this post](https://trekhleb.dev/blog/2021/content-aware-image-resizing-in-javascript/) available where you can upload and resize your custom images.
## TL;DR
There are many great articles written about the *Seam Carving algorithm* already, but I couldn't resist the temptation to explore this elegant, powerful, and *yet simple* algorithm on my own, and to write about my personal experience with it. Another point that drew my attention (as a creator of [javascript-algorithms](https://github.com/trekhleb/javascript-algorithms) repo) was the fact that *Dynamic Programming (DP)* approach might be smoothly applied to solve it. And, if you're like me and still on your "learning algorithms" journey, this algorithmic solution may enrich your personal DP arsenal.
So, with this article I want to do three things:
1. Provide you with an interactive **content-aware resizer** so that you could play around with resizing your own images
2. Explain the idea behind the **Seam Carving algorithm**
3. Explain the **dynamic programming approach** to implement the algorithm (we'll be using TypeScript for it)
### Content-aware image resizing
*Content-aware image resizing* might be applied when it comes to changing the image proportions (i.e. reducing the width while keeping the height) and when losing some parts of the image is not desirable. Doing the straightforward image scaling in this case would distort the objects in it. To preserve the proportions of the objects while changing the image proportions we may use the [Seam Carving algorithm](https://perso.crans.org/frenoy/matlab2012/seamcarving.pdf) that was introduced by *Shai Avidan* and *Ariel Shamir*.
The example below shows how the original image width was reduced by 50% using *content-aware resizing* (left image) and *straightforward scaling* (right image). In this particular case, the left image looks more natural since the proportions of the balloons were preserved.
![Content-aware image resizing](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/01-resizing-options.png)
The Seam Carving algorithm's idea is to find the *seam* (continuous sequence of pixels) with the lowest contribution to the image content and then *carve* (remove) it. This process repeats over and over again until we get the required image width or height. In the example below you may see that the hot air balloon pixels contribute more to the content of the image than the sky pixels. Thus, the sky pixels are being removed first.
![JS IMAGE CARVER DEMO](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/10-demo-01.gif)
Finding the seam with the lowest energy is a computationally expensive task (especially for large images). To make the seam search faster the *dynamic programming* approach might be applied (we will go through the implementation details below).
### Objects removal
The importance of each pixel (so-called pixel's energy) is being calculated based on its color (`R`, `G`, `B`, `A`) difference between two neighbor pixels. Now, if we set the pixel energy to some really low level artificially (i.e. by drawing a mask on top of them), the Seam Carving algorithm would perform an **object removal** for us for free.
![JS IMAGE CARVER OBJECT REMOVAL DEMO](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/10-demo-02.gif)
### JS IMAGE CARVER demo
I've created the [JS IMAGE CARVER](https://trekhleb.dev/js-image-carver/) web-app (and also [open-sourced it on GitHub](https://github.com/trekhleb/js-image-carver)) that you may use to play around with resizing of your custom images.
### More examples
Here are some more examples of how the algorithm copes with more complex backgrounds.
Mountains on the background are being shrunk smoothly without visible seams.
![Resizing demo with more complex backgrounds](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/11-demo-01.png)
The same goes for the ocean waves. The algorithm preserved the wave structure without distorting the surfers.
![Resizing demo with more complex backgrounds](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/11-demo-02.png)
We need to keep in mind that the Seam Carving algorithm is not a silver bullet, and it may fail to resize the images where *most of the pixels are edges* (look important to the algorithm). In this case, it starts distorting even the important parts of the image. In the example below the content-aware image resizing looks pretty similar to a straightforward scaling since for the algorithm all the pixels look important, and it is hard for it to distinguish Van Gogh's face from the background.
![Example when the algorithm does not work as expected](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/12-demo-01.png)
## How Seam Carving algorithms works
Imagine we have a `1000 x 500 px` picture, and we want to change its size to `500 x 500 px` to make it square (let's say the square ratio would better fit the Instagram feed). We might want to set up several **requirements to the resizing process** in this case:
- *Preserve the important parts of the image* (i.e. if there were 5 trees before the resizing we want to have 5 trees after resizing as well).
- *Preserve the proportions* of the important parts of the image (i.e. circle car wheels should not be squeezed to the ellipse wheels)
To avoid changing the important parts of the image we may find the **continuous sequence of pixels (the seam)**, that goes from top to bottom and has *the lowest contribution to the content* of the image (avoids important parts) and then remove it. The seam removal will shrink the image by 1 pixel. We will then repeat this step until the image will get the desired width.
The question is how to define *the importance of the pixel* and its contribution to the content (in the original paper the authors are using the term **energy of the pixel**). One of the ways to do it is to treat all the pixels that form the edges as important ones. In case if a pixel is a part of the edge its color would have a greater difference between the neighbors (left and right pixels) than the pixel that isn't a part of the edge.
![Pixels color difference](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/30-pixel-energy-comparison.png)
Assuming that the color of a pixel is represented by *4* numbers (`R` - red, `G` - green, `B` - blue, `A` - alpha) we may use the following formula to calculate the color difference (the pixel energy):
![Pixel energy formula](https://raw.githubusercontent.com/trekhleb/trekhleb.github.io/master/src/posts/2021/content-aware-image-resizing-in-javascript/assets/20-energy-formula.png)
Where:
- `mEnergy` - *Energy* (importance) of the *middle* pixel (`[0..626]` if rounded)
- `lR` - *Red* channel value for the *left* pixel (`[0..255]`)
- `mR` - *Red* channel value for the *middle* pixel (`[0..255]`)
- `rR` - *Red* channel value for the *right* pixel (`[0..255]`)
- `lG` - *Green* channel value for the *left* pixel (`[0..255]`)
- and so on...
In the formula above we're omitting the alpha (transparency) channel, for now, assuming that there are no transparent pixels in the image. Later we will use the alpha cha
没有合适的资源?快使用搜索试试~ 我知道了~
用 JavaScript 实现的算法和数据结构,并附有解释和进一步阅读的链接
共637个文件
js:351个
md:241个
jpeg:12个
需积分: 0 0 下载量 114 浏览量
2023-10-19
18:30:22
上传
评论
收藏 6.33MB ZIP 举报
温馨提示
该存储库包含许多流行算法和数据结构的基于 JavaScript 的示例。 每个算法和数据结构都有自己单独的自述文件,其中包含相关解释和供进一步阅读的链接(包括 YouTube 视频的链接)。 阅读其他语言版本: 简体中文、 繁体中文、 한국어、 日本语、 波兰语、 法语、 西班牙语、 葡萄牙语、 Русский、 土耳其语、 意大利语、 印度尼西亚语、 Українська、 阿拉伯语、 Tiếng Việt、 德语 请注意,该项目仅用于学习和研究目的,并不用于生产。 数据结构 数据结构是在计算机中组织和存储数据的特殊方式,以便可以有效地访问和修改数据。更准确地说,数据结构是数据值、它们之间的关系以及可应用于数据的函数或操作的集合。 B- 初级,A- 高级 B 链表 B 双向链表 B 队列 B 堆 B 哈希表 B 堆- 最大和最小堆版本 B 优先队列 A 特里树 A 树 A 二叉搜索树 A AVL树 A 红黑树 A 线段树- 带有最小/最大/总和范围查询示例 A Fenwick 树(二元索引树) A 图(有向图和无向图) A 不相交集- 联合查找数据结构或合并查找集 A 布隆
资源推荐
资源详情
资源评论
收起资源包目录
用 JavaScript 实现的算法和数据结构,并附有解释和进一步阅读的链接 (637个子文件)
.babelrc 39B
.editorconfig 201B
.eslintrc 338B
.gitignore 46B
.gitignore 2B
permutations-overview.jpeg 307KB
collision-resolution.jpeg 261KB
tree.jpeg 229KB
doubly-linked-list.jpeg 213KB
linked-list.jpeg 181KB
hash-table.jpeg 161KB
max-heap.jpeg 160KB
queue.jpeg 160KB
min-heap.jpeg 156KB
stack.jpeg 150KB
graph.jpeg 131KB
array-representation.jpeg 129KB
lru-cache.jpg 650KB
permutations-without-repetitions.jpg 364KB
combinations-overview.jpg 345KB
combinations-with-repetitions.jpg 324KB
trie.jpg 302KB
combinations-without-repetitions.jpg 302KB
permutations-with-repetitions.jpg 301KB
stack.jpg 199KB
binary-search-tree.jpg 192KB
Graph.test.js 12KB
RedBlackTree.test.js 10KB
RedBlackTree.js 10KB
Matrix.test.js 9KB
DoublyLinkedList.test.js 8KB
BinaryTreeNode.test.js 8KB
floydWarshall.test.js 8KB
articulationPoints.test.js 8KB
resizeImageWidth.js 8KB
LinkedList.test.js 8KB
AvlTRee.test.js 7KB
FourierTester.js 7KB
Matrix.js 7KB
BinarySearchTreeNode.test.js 7KB
Knapsack.js 7KB
ComplexNumber.test.js 7KB
Heap.js 7KB
breadthFirstSearch.test.js 7KB
depthFirstSearch.test.js 6KB
Knapsack.test.js 6KB
graphBridges.test.js 6KB
DoublyLinkedList.js 6KB
railFenceCipher.js 6KB
LinkedList.js 6KB
GraphVertex.test.js 5KB
SegmentTree.js 5KB
MinHeap.test.js 5KB
eulerianPath.test.js 5KB
zAlgorithm.js 5KB
nQueensBitwise.js 5KB
MaxHeap.test.js 5KB
stronglyConnectedComponents.js 5KB
regularExpressionMatching.js 5KB
LRUCache.test.js 4KB
Graph.js 4KB
LRUCacheOnMap.test.js 4KB
BinaryTreeNode.js 4KB
RadixSort.js 4KB
AvlTree.js 4KB
fastFourierTransform.test.js 4KB
hamiltonianCycle.js 4KB
articulationPoints.js 4KB
BinarySearchTreeNode.js 4KB
ComplexNumber.js 4KB
DisjointSet.test.js 4KB
breadthFirstSearch.test.js 4KB
depthFirstSearch.test.js 4KB
SegmentTree.test.js 4KB
bellmanFord.test.js 4KB
dijkstra.test.js 4KB
LRUCache.js 4KB
bitsToFloat.js 4KB
stronglyConnectedComponents.test.js 4KB
hamiltonianCycle.test.js 4KB
HashTable.test.js 4KB
DisjointSetItem.test.js 4KB
primeFactors.test.js 3KB
PriorityQueue.test.js 3KB
eulerianPath.js 3KB
nQueens.js 3KB
graphBridges.js 3KB
bfTravellingSalesman.js 3KB
detectDirectedCycle.js 3KB
knightTour.js 3KB
HashTable.js 3KB
kMeans.js 3KB
FenwickTree.test.js 3KB
depthFirstSearch.js 3KB
kruskal.test.js 3KB
prim.test.js 3KB
testCases.js 3KB
floydWarshall.js 3KB
BloomFilter.js 3KB
Trie.test.js 3KB
共 637 条
- 1
- 2
- 3
- 4
- 5
- 6
- 7
资源评论
Web面试那些事儿
- 粉丝: 5776
- 资源: 101
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 嵌入式-51单片机原理图
- linux基础操作命令大全
- 奇异谱分析滤波-周期提取-趋势判定-迭代插值的matlab程序
- java源码资源P2P源码 Azureus 2.5.0.2(JAVA)
- TDengine-server-2.0.20.9-Linux-x64
- java源码资源P2P-多用户在线聊天室(Java源码)
- SEW MOVIDRIVE MDX61B调试步骤(extended positioning via bus).pptx
- java源码资源Notebook源码,Java记事本
- 一个简单的Spring Boot天气预报用应用(调用外部的天气API来获取数据)
- EhLib v10.2.42 完整源代码下载
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功