Is there a face in this image? Help, I've been diagnosed with prosopagnosia! This means I'm no longer able to recognise faces.... :(
Can you help me?
The challenge
You will be given an image as a matrix of regular ASCII characters separated by new line characters, and your task is to determine if it contains a face. Faces will look something like the following:
o.o
.7.
___

Of course, people all look different - the only features that virtually everyone has are two eyes, a nose, and a mouth. For this challenge, eyes will be a lower-case o, a nose will be a 7, and the mouth will be a line of underscores _. For this challenge, faces must have all of these features.
To be specific, a face must have two eyes in the same row of the matrix, with a nose centred horizontally between them somewhere between the rows with the eyes and the mouth, and a mouth at the bottom of the face that is a row of underscores that extends all the way from the column of one eye to the other. Since a face must have a horizontally-centred nose, all faces must be an odd number of characters wide. Please note: The nose does not have to be centred vertically so long as it is between the rows of the eyes and mouth (exclusive). No other features of the face matter so long as the face has only two eyes, one nose, and one mouth - the &quot;fill&quot; of the face can be anything but the characters o, 7, or _
The output format is flexible - all you must be able to do is distinguish whether the image from the input has a face. You may use any output values to represent whether an image has a face (e.g. 1 if it does, 0 if it does not)
Examples/Test Cases
...o.....o.
......7....
..._______.

^ contains a face
...o.....o.o.o
......7.....7.
..._______.___

^ contains a face (actually contains two but your program does not need to care about any additional faces)
o.o...o..o
o.7.7._.7.
.._____7__

^ does not contain a face
o.o...o..o
o...7...7.
.._____7__

^ contains a face (notice the two differences between this case and the one above)
o...o
.7...
_____

^ does not contain a face, as the nose is not centred horizontally
..o...o
.......
.......
.......
....7..
.______

^ contains a face formed by the last five columns
,/o[]8o
o198yH3
f_3j`~9
()**&amp;#^
*#&amp;^79%
2______

^ contains a face (the last five columns form a face just like in the previous example, except with different filler characters that make it less human-readable)
o..o.o..o.o...o..o.o.o..o...o.o.o.o.o
......7....o7......7......7......7...
..7...............___......7....___..
____.____.___._.._____.._____._______

^ contains a face (only the 3x3 face in the fifth-last through third-last columns is a face - all the other potential faces break one or more rules)
.....
.o.o.
..7..
.....
.___.

^ contains a face
o7o
...
___

^ does not contain a face
A few extra clarifications
-Faces will never be rotated
-The .'s in the test cases could be any regular ASCII characters other than the three special characters, they are periods just for better readability
-You can assume all matrices will be smaller than 100 x 100
Scoring
This is code-golf. Shortest code wins!
JavaScript (ES6),  147 ... 140  139 bytes
Returns either false or a truthy value.
s=&gt;(p='',g=k=&gt;s.replace(/[^7o_]/g,0).match(`o${p}${p+=0}o${S=`.{${w=s.search`
`-k}}(0${p+p}.{${w}})*`}${p+7+p+S}__{${k}}`)||w&gt;0&amp;&amp;g(k+2))(2)

Try it online!
How?
We start with \$k=2\$ and \$p\$ set to an empty string.
At each iteration, we first replace all characters in the input string \$s\$ other than &quot;o&quot;, &quot;7&quot; or &quot;_&quot; with zeros. This includes linefeeds. So the first test case:
...o.....o.
......7....
..._______.

is turned into:
flat representation: &quot;...o.....o.¶......7....¶..._______.&quot;
after replace()    : &quot;000o00000o00000000700000000_______0&quot;

We then attempt to match the 3 parts of a face of width \$k+1\$.
Eyes
An &quot;o&quot; followed by \$k-1\$ zeros, followed by another &quot;o&quot;:
`o${p}${p+=0}o`

Followed by the padding string \$S\$ defined as:
`.{${w=s.search('\n')-k}}(0${p+p}.{${w}})*`
 \______________________/ \____________/ |
   right / left padding      k+1 zeros   +--&gt; repeated any
                          + same padding      number of times

Nose
\$k/2\$ zeros, followed by a &quot;7&quot;, followed by \$k/2\$ zeros, followed by the same padding string \$S\$ as above:
`${p+7+p+S}`

Mouth
\$k+1\$ underscores:
`__{${k}}`

In case of failure, we try again with \$k+2\$. Or we stop as soon as the variable \$w\$ used to build \$S\$ is less than \$1\$, meaning that the padding string would become inconsistent at the next iteration.
For the first test case, we successively get the following patterns:
o0o.{9}(000.{9})*070.{9}(000.{9})*__{2}
o000o.{7}(00000.{7})*00700.{7}(00000.{7})*__{4}
o00000o.{5}(0000000.{5})*0007000.{5}(0000000.{5})*__{6}

The 3rd one is a match.