Count the Closed Polygons
Python 2, 714 737 821 bytes


-23 bytes thanks to Kevin Cruijssen




M=input()
m=''.join(M)
def P(L):
 if len(L)&lt;2:yield[L];return
 for p in P(L[1:]):
&#9;for n,s in enumerate(p):yield p[:n]+[[L[0]]+s]+p[n+1:]
&#9;yield[[L[0]]]+p
h,w,R,C=len(M),len(M[0]),0,[-1,0,1]
K=[(i,j)for i in range(h)for j in range(w)]
Z=[(i,j)for i,j in K if' '==M[i][j]]
from networkx import*
for l in set(m):
 G,S=[],[]
 if l in'oO0':R+=m.count(l);continue
 for I in K:
  i,j=I
  for p in C:
&#9;for q in C:
&#9; X=x,y=i+p,j+q
&#9; if X in K and X!=I and set(M[i][j]+M[x][y])&lt;=set(' '+l):G+=[(I,X)];S+=[I,X]
 B=0
 for L in P(list(set(S))):
  b=0
  for p in L:
&#9;for i,j in p:
&#9; if' '!=M[i][j]:&#32;
&#9;&#9;try:find_cycle(from_edgelist([(I,X)for I,X in G if I in p+Z and X in p+Z]));b+=1
&#9;&#9;except:1
&#9;&#9;break
&#9;if b&gt;B:B=b
 R+=B
print R


Try it online!


For each letter A (except  o, O, and 0) the code build a graph representing the adjacency of the different occurrences of letter A and space in the initial given matrix. Then it computes the set of semi-separated cycles covering the graph when maximizing the number of cycles (separation is based only on the letter A, the same space can be used for several cycles). 
The code passes all tests.
Input: the list of lines of the matrix.
More explanation and golfing coming soon.