{"id":260,"date":"2009-05-15T07:00:57","date_gmt":"2009-05-15T11:00:57","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/15\/continental-divide-4-oceans\/"},"modified":"2019-10-28T15:32:35","modified_gmt":"2019-10-28T19:32:35","slug":"continental-divide-4-oceans","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/15\/continental-divide-4-oceans\/","title":{"rendered":"Locating the US continental divide, part 4 &#8211; Ocean masks"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>Welcome to part 4 of my <a href=\"https:\/\/blogs.mathworks.com\/steve\/category\/continental-divide\/\">series<\/a> on computing the US continental divide. Previously we looked at data import and display, the watershed transform and label\r\n      matrices, and different kinds of minima.\r\n   <\/p>\r\n   <p>Today we're going to use some binary image manipulation to create an \"ocean mask.\" Let's start by taking a fresh look at some\r\n      of the pixel values in the DEM (digital elevation model) we've been working with.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">s = load(<span style=\"color: #A020F0\">'continental_divide'<\/span>);\r\ndem = s.dem_cropped;\r\ndisplay_range = [-500 3000];\r\nimshow(dem, display_range, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/continental_divide_part_4_ocean_mask_01.jpg\"> <p>What are the pixel values associated with the ocean?  You might expect them to be 0. After all, the ocean is at sea level!\r\n       But a few values at the upper-left corner of the DEM are not 0:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">dem(1:5, 1:5)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n   -500   -500   -500   -500   -500\r\n   -500   -500   -500   -500   -500\r\n   -500   -500   -500   -500   -500\r\n   -500   -500   -500   -500   -500\r\n   -500   -500   -500   -500   -500\r\n\r\n<\/pre><p>Are the ocean pixels equal to -500 all the way up to the coast? When I want to inspect pixel values closely, I often use the\r\n      <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2009a\/toolbox\/images\/impixelregion.html\">Pixel Region Tool<\/a>. Here's a screen shot of the tool showing pixel values along the coast of California:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/pixel_region_tool_screenshot.png\"> <\/p>\r\n   <p>So the value -500 seems to be used as an ocean marker value. But I prefer not to guess. After some browsing of the <a href=\"http:\/\/www.ngdc.noaa.gov\/mgg\/topo\/report\/index.html\">online report<\/a> about this data set, I found this sentence in <a href=\"http:\/\/www.ngdc.noaa.gov\/mgg\/topo\/report\/s11\/s11C.html\">Section 11<\/a>: \"Every tile contains values of -500 for oceans, with no values between -500 and the minimum value for land noted here.\"\r\n   <\/p>\r\n   <p>We can use a simple relational operator to form an ocean mask image.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">ocean_mask = dem == -500;\r\nimshow(ocean_mask, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/continental_divide_part_4_ocean_mask_02.jpg\"> <p>I expected <tt>ocean_mask<\/tt> to have just two connected components, corresponding to the Pacific and Atlantic Oceans. But I was surprised:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">ocean_mask_labeled = bwlabel(ocean_mask);\r\nmax(ocean_mask_labeled(:))<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n   835\r\n\r\n<\/pre><p>Oops. More than 800 labeled regions, not two. Let's zoom in the coast of the Gulf of Mexico to see what's going on.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">axis([3700 4300 2500 2800])<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/continental_divide_part_4_ocean_mask_03.jpg\"> <p>You can see that there are \"ocean\" pixels that are completely disconnected from the rest of the oceans.  How can we identify\r\n      just the connected components of ocean pixels on the left and right side of the DEM?  One method is to use <tt>bwselect<\/tt>.  This function can find all foreground pixels that are \"connected\" to a given set of seed pixels. Here I'll use it to find\r\n      all the \"ocean\" pixels connected to the upper left and upper right components.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[M, N] = size(dem);\r\nocean_mask = bwselect(ocean_mask, [1 N], [1 1]);<\/pre><p>Here's the same zoomed-in view along the Gulf of Mexico.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imshow(ocean_mask, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)\r\naxis([3800 4400 2550 2750])<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2009\/continental_divide_part_4_ocean_mask_04.jpg\"> <p>You can see that the interior \"ocean pixels\" have been removed. Let's add this image to our continental divide MAT-file.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">save <span style=\"color: #A020F0\">continental_divide<\/span> <span style=\"color: #A020F0\">ocean_mask<\/span> <span style=\"color: #A020F0\">-append<\/span><\/pre><p>Next time we'll use a technique called <i>minima imposition<\/i> to modify the DEM so that it contains only two regional minima, one for each ocean.\r\n   <\/p>\r\n   <p><i>About this Series<\/i><\/p>\r\n   <p><a href=\"https:\/\/blogs.mathworks.com\/steve\/category\/continental-divide\/\">This series<\/a> explores the problem of computing the location of the continental divide for the United States.  The divide separates the\r\n      Atlantic and Pacific Ocean catchment basins for the North American continent.\r\n   <\/p>\r\n   <p>As an algorithm development problem, computing the divide lets us explore aspects of data import and visualization, manipulating\r\n      binary image masks, label matrices, regional minima, and the watershed transform.\r\n   <\/p>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/04\/24\/continental-divide-1-intro\/\">Part 1<\/a> - Introduction. Data import and display. <tt>multibandread<\/tt>, <tt>imshow<\/tt>.\r\n         <\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/01\/continental-divide-2-watershed\/\">Part 2<\/a> - Watershed transform. <tt>watershed<\/tt>, <tt>label2rgb<\/tt>.\r\n         <\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/08\/continental-divide-3-regmin\/\">Part 3<\/a> - Regional minima. <tt>imerode<\/tt>, <tt>imregionalmin<\/tt>.\r\n         <\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/15\/continental-divide-4-oceans\/\">Part 4<\/a> - Ocean masks. binary image manipulation, <tt>bwselect<\/tt>.\r\n         <\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/22\/continental-divide-5-imposemin\/\">Part 5<\/a> - Minima imposition. <tt>imimposemin<\/tt>.\r\n         <\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/29\/continental-divide-6-watershed\/\">Part 6<\/a> - Computing and visualizing the divide. <tt>watershed<\/tt>, <tt>label2rgb<\/tt>, <tt>bwboundaries<\/tt>.\r\n         <\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/06\/05\/continental-divide-7-all-steps\/\">Part 7<\/a> - Putting it all together. One script that does everything, from data import through computation and visualization\r\n            of the divide.\r\n         <\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <p>Data credit: <i>GLOBE Task Team and others (Hastings, David A., Paula K. Dunbar, Gerald M. Elphingstone, Mark Bootz, Hiroshi Murakami, Hiroshi\r\n         Maruyama, Hiroshi Masaharu, Peter Holland, John Payne, Nevin A. Bryant, Thomas L. Logan, J.-P. Muller, Gunter Schreier, and\r\n         John S. MacDonald), eds., 1999. The Global Land One-kilometer Base Elevation (GLOBE) Digital Elevation Model, Version 1.0.\r\n         National Oceanic and Atmospheric Administration, National Geophysical Data Center, 325 Broadway, Boulder, Colorado 80305-3328,\r\n         U.S.A. Digital data base on the World Wide Web (URL: <a href=\"http:\/\/www.ngdc.noaa.gov\/mgg\/topo\/globe.html\">http:\/\/www.ngdc.noaa.gov\/mgg\/topo\/globe.html<\/a>) and CD-ROMs.<\/i><\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_aeaff705d800466c906acf9178289b52() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='aeaff705d800466c906acf9178289b52 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' aeaff705d800466c906acf9178289b52';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        author = 'Steve Eddins';\r\n        copyright = 'Copyright 2009 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n      \r\n-->\r\n<\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_aeaff705d800466c906acf9178289b52()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.8<br><\/p>\r\n<\/div>\r\n<!--\r\naeaff705d800466c906acf9178289b52 ##### SOURCE BEGIN #####\r\n%%\r\n% Welcome to part 4 of my\r\n% <https:\/\/blogs.mathworks.com\/steve\/category\/continental-divide\/ series> on \r\n% computing the US continental divide. Previously we looked at data import\r\n% and display, the watershed transform and label matrices, and different\r\n% kinds of minima.\r\n%\r\n% Today we're going to use some binary image manipulation to create an\r\n% \"ocean mask.\" Let's start by taking a fresh look at some of the pixel\r\n% values in the DEM (digital elevation model) we've been working with.\r\n\r\ns = load('continental_divide');\r\ndem = s.dem_cropped;\r\ndisplay_range = [-500 3000];\r\nimshow(dem, display_range, 'InitialMagnification', 'fit')\r\n\r\n%%\r\n% What are the pixel values associated with the ocean?  You might expect\r\n% them to be 0. After all, the ocean is at sea level!  But a few values at\r\n% the upper-left corner of the DEM are not 0:\r\n\r\ndem(1:5, 1:5)\r\n\r\n%%\r\n% Are the ocean pixels equal to -500 all the way up to the coast? When I\r\n% want to inspect pixel values closely, I often use the \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2009a\/toolbox\/images\/impixelregion.html Pixel Region Tool>. \r\n% Here's a screen shot of the tool showing pixel values along the coast of\r\n% California:\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2009\/pixel_region_tool_screenshot.png>>\r\n%\r\n% So the value -500 seems to be used as an ocean marker value. But I prefer\r\n% not to guess. After some browsing of the \r\n% <http:\/\/www.ngdc.noaa.gov\/mgg\/topo\/report\/index.html online report> about\r\n% this data set, I found this sentence in \r\n% <http:\/\/www.ngdc.noaa.gov\/mgg\/topo\/report\/s11\/s11C.html Section 11>:\r\n% \"Every tile contains values of -500 for oceans, with no values between\r\n% -500 and the minimum value for land noted here.\"\r\n%\r\n% We can use a simple relational operator to form an ocean mask image.\r\n\r\nocean_mask = dem == -500;\r\nimshow(ocean_mask, 'InitialMagnification', 'fit')\r\n\r\n%%\r\n% I expected |ocean_mask| to have just two connected components,\r\n% corresponding to the Pacific and Atlantic Oceans. But I was surprised:\r\n\r\n\r\nocean_mask_labeled = bwlabel(ocean_mask);\r\nmax(ocean_mask_labeled(:))\r\n\r\n%%\r\n% Oops. More than 800 labeled regions, not two. Let's zoom in the coast of the\r\n% Gulf of Mexico to see what's going on.\r\n\r\naxis([3700 4300 2500 2800])\r\n\r\n%%\r\n% You can see that there are \"ocean\" pixels that are completely\r\n% disconnected from the rest of the oceans.  How can we identify just the\r\n% connected components of ocean pixels on the left and right side of the\r\n% DEM?  One method is to use |bwselect|.  This function can find all\r\n% foreground pixels that are \"connected\" to a given set of seed pixels.\r\n% Here I'll use it to find all the \"ocean\" pixels connected to the upper\r\n% left and upper right components.\r\n\r\n[M, N] = size(dem);\r\nocean_mask = bwselect(ocean_mask, [1 N], [1 1]);\r\n\r\n%%\r\n% Here's the same zoomed-in view along the Gulf of Mexico.\r\n\r\nimshow(ocean_mask, 'InitialMagnification', 'fit')\r\naxis([3800 4400 2550 2750])\r\n\r\n%%\r\n% You can see that the interior \"ocean pixels\" have been removed. Let's\r\n% add this image to our continental divide MAT-file.\r\n\r\nsave continental_divide ocean_mask -append\r\n\r\n%%\r\n% Next time we'll use a technique called _minima imposition_ to modify the\r\n% DEM so that it contains only two regional minima, one for each ocean.\r\n%\r\n%%\r\n% _About this Series_ \r\n%\r\n% <https:\/\/blogs.mathworks.com\/steve\/category\/continental-divide\/ This\r\n% series> explores the problem of computing the location of the \r\n% continental divide for the United States.  The divide separates the\r\n% Atlantic and Pacific Ocean catchment basins for the North American\r\n% continent.\r\n%\r\n% As an algorithm development problem, computing the divide lets us\r\n% explore aspects of data import and visualization, manipulating binary\r\n% image masks, label matrices, regional minima, and the watershed\r\n% transform.\r\n%\r\n% * Part 1 - Introduction. Data import and display. |multibandread|,\r\n% |imshow|. \r\n%\r\n% * Part 2 - Watershed transform. |watershed|, |label2rgb|.\r\n%\r\n% * Part 3 - Regional minima. |imerode|, |imregionalmin|.\r\n%\r\n% * Part 4 - Ocean masks. binary image manipulation, |bwselect|.\r\n%\r\n% * Part 5 - Minima imposition. |imimposemin|.\r\n%\r\n% * Part 6 - Computing and visualizing the divide. |watershed|,\r\n% |label2rgb|, |bwboundaries|. \r\n%\r\n% * Part 7 - Putting it all together. One script that does everything, from\r\n% data import through computation and visualization of the divide.\r\n%\r\n% Data credit: _GLOBE Task Team and others (Hastings, David A., Paula K.\r\n% Dunbar, Gerald M. Elphingstone, Mark Bootz, Hiroshi Murakami, Hiroshi\r\n% Maruyama, Hiroshi Masaharu, Peter Holland, John Payne, Nevin A. Bryant,\r\n% Thomas L. Logan, J.-P. Muller, Gunter Schreier, and John S. MacDonald),\r\n% eds., 1999. The Global Land One-kilometer Base Elevation (GLOBE) Digital\r\n% Elevation Model, Version 1.0. National Oceanic and Atmospheric\r\n% Administration, National Geophysical Data Center, 325 Broadway, Boulder,\r\n% Colorado 80305-3328, U.S.A. Digital data base on the World Wide Web (URL:\r\n% http:\/\/www.ngdc.noaa.gov\/mgg\/topo\/globe.html) and CD-ROMs._\r\n##### SOURCE END ##### aeaff705d800466c906acf9178289b52\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   Welcome to part 4 of my series on computing the US continental divide. Previously we looked at data import and display, the watershed transform and label\r\n      matrices, and different kinds of... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/05\/15\/continental-divide-4-oceans\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[19],"tags":[50,166,418,36,362,122,553,190],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/260"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/comments?post=260"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/260\/revisions"}],"predecessor-version":[{"id":3629,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/260\/revisions\/3629"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=260"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=260"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=260"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}