| Bytes | Lang | Time | Link |
|---|---|---|---|
| 161 | Python3 | 250331T023810Z | Ajax1234 |
| 019 | Japt | 160206T182418Z | ETHprodu |
| 042 | MATL | 160206T013501Z | Luis Men |
| 114 | ES6 | 160206T001748Z | Neil |
| 023 | Pyth | 160206T000413Z | Maltysen |
| 008 | Snails | 160206T000447Z | feersum |
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)))
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.
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" #
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.