#include <bits/stdc++.h>
using namespace std;
int err;
int bitc(long long r) { return r == 0 ? 0 : (bitc(r >> 1) + (r & 1)); }
long long gcd(long long x, long long y) { return x ? gcd(y % x, x) : y; }
string cts(char c) {
  string s = "";
  s += c;
  return s;
}
char buf[1000000];
string getLine() {
  string s;
  while (!feof(stdin)) {
    char c = fgetc(stdin);
    if (c == 13) continue;
    if (c == 10) return s;
    s += c;
  }
  return s;
}
int getNum() {
  string s = getLine();
  return atoi(s.c_str());
}
vector<int> parsevi(string s) {
  s = s + " ";
  int q = 0;
  bool minus = false;
  vector<int> res;
  for (typeof(0) l = (0); l < ((int(s.size()))); ++l) {
    if (s[l] == ' ') {
      res.push_back(minus ? -q : q);
      q = 0;
      minus = false;
    } else if (s[l] == '-') {
      minus = true;
    } else {
      q = q * 10 + s[l] - '0';
    }
  }
  return res;
}
int Cases, cnum;
int K;
int X, Y;
short bmp[1600][1600];
int uds[1600][1600];
int dfsres;
void dfs1(short x, short y) {
  if (bmp[y][x] != 1) return;
  bmp[y][x] = 0;
  dfs1(x - 1, y);
  dfs1(x + 1, y);
  dfs1(x, y - 1);
  dfs1(x, y + 1);
}
void dfs3(short x, short y) {
  if (bmp[y][x] == 0) return;
  if (bmp[y][x] == 1) {
    dfs1(x, y);
    dfsres++;
    return;
  }
  bmp[y][x] = 0;
  dfs3(x - 1, y);
  dfs3(x + 1, y);
  dfs3(x, y - 1);
  dfs3(x, y + 1);
}
void solveCase() {
  int res = 0;
  err = scanf("%d%d", &Y, &X);
  for (typeof(0) y = (0); y < (Y); ++y)
    for (typeof(0) x = (0); x < (X); ++x) {
      int b;
      err = scanf("%d", &b);
      bmp[y][x] = b;
    }
  for (typeof(0) y = (0); y < (Y); ++y)
    for (typeof(1) x = (1); x < (X); ++x)
      uds[y][x] = uds[y][x - 1] + bmp[y][x - 1];
  for (typeof(1) y = (1); y < (Y); ++y)
    for (typeof(0) x = (0); x < (X); ++x) uds[y][x] = uds[y][x] + uds[y - 1][x];
  for (typeof(0) y = (0); y < (Y); ++y)
    for (typeof(0) x = (0); x < (X); ++x)
      if (y == 0 || x == 0 || y == Y - 1 || x == X - 1) bmp[y][x] = 0;
  for (typeof(4) y = (4); y < (Y - 4); ++y)
    for (typeof(4) x = (4); x < (X - 4); ++x) {
      int tot = uds[y + 4][x + 4] - uds[y - 4][x + 4] - uds[y + 4][x - 4] +
                uds[y - 4][x - 4];
      if (tot == 64) bmp[y][x] = 2;
    }
  for (typeof(0) y = (0); y < (Y); ++y)
    for (typeof(0) x = (0); x < (X); ++x) uds[y][x] = (bmp[y][x] == 2) ? 1 : 0;
  for (typeof(0) y = (0); y < (Y); ++y)
    for (typeof(1) x = (1); x < (X); ++x) uds[y][x] = uds[y][x - 1] + uds[y][x];
  for (typeof(1) y = (1); y < (Y); ++y)
    for (typeof(0) x = (0); x < (X); ++x) uds[y][x] = uds[y][x] + uds[y - 1][x];
  for (typeof(6) y = (6); y < (Y - 6); ++y)
    for (typeof(6) x = (6); x < (X - 6); ++x) {
      int tot = uds[y + 6][x + 6] - uds[y - 6][x + 6] - uds[y + 6][x - 6] +
                uds[y - 6][x - 6];
      if (tot > 0) bmp[y][x] = 3;
    }
  vector<int> v;
  for (typeof(0) y = (0); y < (Y); ++y)
    for (typeof(0) x = (0); x < (X); ++x)
      if (bmp[y][x] == 3) {
        dfsres = 0;
        dfs3(x, y);
        v.push_back(dfsres);
      }
  if (0)
    for (typeof(0) y = (0); y < (Y); ++y) {
      for (typeof(0) x = (0); x < (X); ++x) printf("%d", bmp[y][x]);
      printf("\n");
    }
  sort(v.begin(), v.end());
  printf("%d\n", (int(v.size())));
  for (typeof(0) a = (0); a < ((int(v.size()))); ++a)
    printf("%d%c", v[a], a == (int(v.size())) - 1 ? '\n' : ' ');
}
int main() {
  if (1)
    Cases = 1;
  else if (0) {
    string Nstr = getLine();
    Cases = atoi(Nstr.c_str());
  } else {
    err = scanf("%d", &Cases);
  }
  for (cnum = 1; cnum <= Cases; cnum++) solveCase();
  return 0;
}
