g | x | w | all
Bytes Lang Time Link
161Python3250331T023810ZAjax1234
019Japt160206T182418ZETHprodu
042MATL160206T013501ZLuis Men
114ES6160206T001748ZNeil
023Pyth160206T000413ZMaltysen
008Snails160206T000447Zfeersum

Python3, 161 bytes

E=enumerate
def f(b):d={(x,y):v for x,r in E(b)for y,v in E(r)};return sum(not d.get((x+X,y+Y))for x,y in d for X,Y in[(1,0),(-1,0),(0,-1),(0,1)]if d.get((x,y)))

Try it online!

Japt, 22 19 bytes

4o £UzX è"#%s|#$} x

Assumes the input is padded with spaces to form a rectangle. Test it online!

How it works

          // Implicit: U = input string, S = a space
4o £    } // Create the array [0,1,2,3], and map each item X to:
UzX       //  Rotate U by 90 degrees X times.
è"#%s|#$  //  Count the number of "#"s followed by a space, newline, or end-of-string.
x         // Sum the resulting array.

MATL, 42 bytes

c2\FTFt!*Y+2*qFTFtl-4lhhbvv_2X53$Y+t0>)s2/

This accepts the input as a cell array of strings, of the form

{'#####', '#   #', '# # #', '#   #', '#####'}

It first converts the input to a 2D char array, padding with spaces, and then to a matrix of zeros and ones. 2D-convolution is then applied twice, with two different masks: first for expanding the matrix, second for detecting edges.

Try it online!

ES6, 123 115 114 bytes

a=>a.map((s,i)=>s.replace(/#/g,(h,j)=>r+=(s[j-1]!=h)+(s[j+1]!=h)+((a[i-1]||'')[j]!=h)+((a[i+1]||'')[j]!=h)),r=0)|r

Edit: Saved 9 bytes thanks to @edc65.

Pyth - 25 23 bytes

First it pads the input to a rect. Then counts the occurrences of " #" over the 4 permutations of transpositions and reversals of the input+space.

/ssm_B++;j;d;CB.t.zd" #

Try it online here.

Snails, 8 bytes

A
\#o!\#

​​​​​The A option means to count all matching paths rather which starting points a match succeeds from. \# consumes a #, o turns in a cardinal direction, and !\# is a negative assertion which succeeds if there is not a # in front of us.