{"id":25,"date":"2005-11-14T09:32:00","date_gmt":"2005-11-14T14:32:00","guid":{"rendered":"http:\/\/wangxiaohu.com\/blog\/?p=25"},"modified":"2005-11-14T09:32:00","modified_gmt":"2005-11-14T14:32:00","slug":"image-compression-using-svd","status":"publish","type":"post","link":"https:\/\/wangxiaohu.com\/blog\/?p=25","title":{"rendered":"Image Compression Using SVD"},"content":{"rendered":"<p>Introduced by one of best friend, <a href=\"http:\/\/optlab.mcmaster.ca\/~huangs3\/\">Sui Huang<\/a>, I recently learned how to use <a href=\"http:\/\/www.mathworks.com\/access\/helpdesk\/help\/techdoc\/ref\/svd.html\"><code><abbr title=\"Singular Value Decomposition\">svd<\/abbr><\/code> function<\/a> in <a href=\"http:\/\/www.mathworks.com\/\">Matlab<\/a> to compress an image, which in my opinion is easier to be understood and implemented. Instead of the algorithm inside <code>svd<\/code>, only its usage is discussed below.<\/p>\n<p><code>svd<\/code> is a function which allows any matrix <em>M<\/em> with arbitrary size <em>m<\/em> by <em>n<\/em>, to be decomposited into 3 matrices, <em>U<\/em> (<em>m<\/em> by <em>m<\/em>), <em>S<\/em> (<em>m<\/em> by <em>n<\/em>) and <em>V<\/em> (<em>n<\/em> by <em>n<\/em>), such that<\/p>\n<blockquote>\n<p><code>M = U * S * V'<\/code>.<\/p>\n<\/blockquote>\n<p><em>S<\/em> is a diagonal matrix with its non-negative elements sorted in decreasing order diagonally, whereas <em>U<\/em> and <em>V<\/em> are unitary matrices. Note that those elements with larger value in <em>S<\/em> are more important to the content of an image. The idea of compressing the image is that only first number of diagonal elements in <em>S<\/em>, with corresponding columns and rows in <em>U<\/em> and <em>V<\/em> are saved. Other elements in these matrices are not saved since they are less important to the image content. Depending on different saving selections, the quality of the image varies. The actual steps of compressing and restoring an image are shown in the following Matlab statements.<\/p>\n<p>First we use <code>imread<\/code> function to read a image into matrix <em>M<\/em>. Since usually the given image contains 3 layers, red, green and blue, to simplify the steps, we assume that only one layer, <em>M<\/em>, is to be compressed:<\/p>\n<blockquote>\n<p><code>[M1, M2, M3] = imread ('<em>filename<\/em>&#8216;,&#8217;<em>format<\/em>&#8216;);<br \/>\nM = double (M1);<br \/>\n<\/code><\/p>\n<\/blockquote>\n<p>Here <code><em>filename<\/em><\/code> is the file name of the image and <code><em>format<\/em><\/code> is the image type of the <code><em>filename<\/em><\/code>, such as <code>jpg<\/code>, <code>gif<\/code> and etc.<\/p>\n<p>Next, we use <code>svd<\/code> to decompose <em>M<\/em> into three matrices:<\/p>\n<blockquote>\n<p><code>[U, S, V] = svd (M);<\/code><\/p>\n<\/blockquote>\n<p>and we trim each of them with only first 10 valuable columns and rows saved:<\/p>\n<blockquote>\n<p><code>U = U(:, 1:10);<br \/>\nV = V(:, 1:10);<br \/>\nS = S(1:10, 1:10);<br \/>\n<\/code><\/p>\n<\/blockquote>\n<p>Now we restore the image using new <em>U<\/em>, <em>V<\/em> and <em>S<\/em> matrices, and save it to a file:<\/p>\n<blockquote>\n<p><code>M = U * S * V';<br \/>\nM1 = uint8 (M);<br \/>\nimwrite ([M1, M2, M3], &#8216;<em>filename<\/em>&#8216;, &#8216;<em>format<\/em>&#8216;);<br \/>\n<\/code><\/p>\n<\/blockquote>\n<p>Thanks Sui for providing the full <a href=\"http:\/\/www.cas.mcmaster.ca\/~wangy22\/public\/degradepic.m\">source code<\/a>. With variable <code>r<\/code> in the code set to 20 and 10 respectively, given an input image, two output images were generated:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.cas.mcmaster.ca\/~wangy22\/public\/svdtest.jpg?w=660\" alt=\"input\" class=\"centered\" data-recalc-dims=\"1\"\/><br \/>\n<img decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.cas.mcmaster.ca\/~wangy22\/public\/svdtest20.jpg?w=660\" alt=\"r = 20\" data-recalc-dims=\"1\" \/><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/www.cas.mcmaster.ca\/~wangy22\/public\/svdtest10.jpg?w=660\" alt=\"r = 10\" data-recalc-dims=\"1\" \/><\/p>\n<p>As can be seen, the qualities of output images are very low, thus cannot be used in any image processing tasks that have high demands on picture quality, since this method just manipulate matrices, with no image analyzing at all. But still, it is possible to combine with other image processing techniques together, to compensate its weakness, and become useful for programs such as object recognition and video streaming.<\/p>\n<p><strong>Update:<\/strong><\/p>\n<p>According to the <a href=\"http:\/\/wangxiaohu.com\/index.php\/2005\/11\/14\/image-compressing-using-svd\/#comments\">comments<\/a>, we can use <a href=\"http:\/\/www.netlib.org\/lanczos\/\">Lanczos<\/a> method to compute &#8220;<em>only large singular values and singular vectors (columns of U and V are actually singular vectors)<\/em>&#8220;, to simply the calculation and save more memory during the process. Thanks to Sui Huang and <a href=\"http:\/\/www.cas.mcmaster.ca\/~qiao\">Dr. Qiao<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduced by one of best friend, Sui Huang, I recently &hellip; <a href=\"https:\/\/wangxiaohu.com\/blog\/?p=25\" class=\"more-link\">\u7ee7\u7eed\u9605\u8bfb<span class=\"screen-reader-text\">Image Compression Using SVD<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_jetpack_memberships_contains_paid_content":false},"categories":[1],"tags":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","jetpack_likes_enabled":true,"jetpack-related-posts":[],"jetpack_shortlink":"https:\/\/wp.me\/pdhZ2A-p","_links":{"self":[{"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25"}],"collection":[{"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=25"}],"version-history":[{"count":0,"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25\/revisions"}],"wp:attachment":[{"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=25"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=25"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wangxiaohu.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=25"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}