# 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 的算法与数据结构,源代码
共628个文件
js:357个
md:228个
jpeg:12个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 198 浏览量
2024-03-27
21:08:20
上传
评论
收藏 6.23MB ZIP 举报
温馨提示
链表 双链表 队列 叠 哈希表 堆 - 最大和最小堆版本 优先队列 Trie 树 二叉搜索树 AVL树 红黑树 区段树 - 包含最小/最大/总和范围查询示例 Fenwick Tree(二叉索引树) 图形(有向和无向) Disjoint Set - 并集 - 查找数据结构或合并 - 查找集 绽放过滤器 LRU 缓存 - 最近最少使用 (LRU) 缓存
资源推荐
资源详情
资源评论
收起资源包目录
多种基于JavaScript 的算法与数据结构,源代码 (628个子文件)
.babelrc 39B
.editorconfig 201B
.eslintrc 338B
.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
dijkstra.js 3KB
共 628 条
- 1
- 2
- 3
- 4
- 5
- 6
- 7
资源评论
新华
- 粉丝: 8572
- 资源: 609
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 原生微信小程序源码 - -仿豆瓣图书
- 原生微信小程序源码 - -滴滴公交-查公交
- 人工智能实验四 感知器算法的设计实现
- java小项目多线程多线程 复制文件 冒泡排序 群聊
- 四数之和(java代码).docx
- 701837906919458TapScanner v3.0.10 (Pro).apk
- 青岛大学人工智能实验二 利用α-β搜索的博弈树算法编写一字棋游戏
- ### 1、项目介绍 本项目Scrapy进行数据爬取,并使用Django框架+PyEcharts实现可视化大屏 效果如下:
- # 微信小程序-健康菜谱 基于微信小程序的一个查找检索菜谱的应用 ### 效果 !动态图(./res/gif/demo
- zabbix-get命令包资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功