J, 58 bytes
f=.{~0==/@]
[:(,/"2)2 2((' _'f{."1),' |'f{.);.3 1:+<.@%&10
An anonymous function which takes a matrix and outputs the contours.
Lotta room for improvement here. I didn't have time to try all the test cases so let me know if there are any issues. Will try to golf more and explain later.
(Quick) Explanation
Helper function: indexes into a length 2 string based on whether the first element of a 2 length array is equal to the second. If it is equal, it indexes into the zeroth element, if it is unequal, it indexes into the first. A 1 length array always indexes into the zeroth element of the string.
f=.{~0==/@]
Main function
[:(,/"2)2 2((' _'f{."1),' |'f{.);.3 1:+<.@%&10
1:+<.@%&10
floors each element divided by 10 and adds 1 (so we will never get 0 -- this is important for the helper function).
2 2((' _'f{."1),' |'f{.);.3
cuts the matrix into 2 x 2 segments if it can (otherwise it'll give a 2 x 1, 1 x 2, or 1 x 1 segment near the edges) and applies the function that uses f
to compare the top left element to the top right and the top left element to the bottom left.
(,/"2)
flattens the result into the desired shape. I really feel like I should be able to avoid having to use this (and a lot of other things, but I digress).