#include <bits/stdc++.h>
using namespace std;
int const MAXN = 1610;
int const INF = 1000000000;
int const DX[4] = {-1, 1, 0, 0};
int const DY[4] = {0, 0, -1, 1};
int const DX_8[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
int const DY_8[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
int const MEGA_DIR_X[4] = {-1, 0, 1, 0};
int const MEGA_DIR_Y[4] = {0, 1, 0, -1};
int s[MAXN][MAXN], nnew[MAXN][MAXN], nnew_save[MAXN][MAXN], marked[MAXN][MAXN];
int min_H[MAXN * MAXN], max_H[MAXN * MAXN], min_W[MAXN * MAXN],
    max_W[MAXN * MAXN], ans_count[MAXN * MAXN], ans_ind[MAXN * MAXN];
struct {
  int x, y;
} och[MAXN * MAXN];
int const THR = 8;
int const DRR = 6;
int main() {
  int h, w;
  scanf("%d%d", &h, &w);
  for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++) scanf("%d", &s[i][j]);
  int color = 0;
  int ans = 0;
  for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++)
      if (s[i][j] && !nnew[i][j]) {
        color++;
        nnew[i][j] = color;
        int p_read = 0, p_write = 1;
        och[0].x = i;
        och[0].y = j;
        while (p_read < p_write) {
          int x = och[p_read].x;
          int y = och[p_read].y;
          p_read++;
          for (int k = 0; k < 4; k++) {
            int new_x = x + DX[k];
            int new_y = y + DY[k];
            if (new_x >= 0 && new_x < h && new_y >= 0 && new_y < w &&
                s[new_x][new_y] && !nnew[new_x][new_y]) {
              nnew[new_x][new_y] = color;
              och[p_write].x = new_x;
              och[p_write].y = new_y;
              p_write++;
            }
          }
        }
        ans++;
      }
  cout << ans << "\n";
  for (int i = 0; i <= color; i++) {
    min_H[i] = INF;
    max_H[i] = -INF;
    min_W[i] = INF;
    max_W[i] = -INF;
  }
  for (int i = 0; i < h; i++) {
    int last_j = -1;
    for (int j = 0; j <= w; j++)
      if (s[i][j]) {
        if (last_j == -1) last_j = j;
      } else {
        if (last_j != -1) {
          int bg_p = last_j;
          int en_p = j - 1;
          int len = en_p - bg_p + 1;
          int cur_color = nnew[i][bg_p];
          if (len >= THR) {
            min_H[cur_color] = min(min_H[cur_color], i);
            max_H[cur_color] = max(max_H[cur_color], i);
          }
          last_j = -1;
        }
      }
  }
  for (int j = 0; j < w; j++) {
    int last_i = -1;
    for (int i = 0; i <= h; i++)
      if (s[i][j]) {
        if (last_i == -1) last_i = i;
      } else {
        if (last_i != -1) {
          int bg_p = last_i;
          int en_p = i - 1;
          int len = en_p - bg_p + 1;
          int cur_color = nnew[bg_p][j];
          if (len >= THR) {
            min_W[cur_color] = min(min_W[cur_color], j);
            max_W[cur_color] = max(max_W[cur_color], j);
          }
          last_i = -1;
        }
      }
  }
  for (int i = 0; i <= color; i++)
    if (min_H[i] != INF) {
      int R = min((max_H[i] - min_H[i]) / 2, (max_W[i] - min_W[i]) / 2) + DRR;
      int c_x = (max_H[i] + min_H[i]) / 2;
      int c_y = (max_W[i] + min_W[i]) / 2;
      for (int j = min_H[i]; j <= max_H[i]; j++)
        for (int k = min_W[i]; k <= max_W[i]; k++)
          if (((j - c_x) * (j - c_x) + (k - c_y) * (k - c_y)) <= R * R)
            nnew[j][k] = 0;
    }
  int const new_THR = 3;
  for (int i = 0; i < h; i++) {
    int last_j = -1;
    for (int j = 0; j <= w; j++)
      if (nnew[i][j]) {
        if (last_j == -1) last_j = j;
      } else {
        if (last_j != -1) {
          int bg_p = last_j;
          int en_p = j - 1;
          int len = en_p - bg_p + 1;
          int cur_color = nnew[i][bg_p];
          if (len >= new_THR) {
            int Ok = 0;
            int ppp = -1;
            for (int q = bg_p; q <= en_p; q++)
              if (i + 1 < h && q + 2 < w && q + 2 <= en_p &&
                  nnew[i + 1][q] == cur_color &&
                  nnew[i + 1][q + 1] == cur_color &&
                  nnew[i + 1][q + 2] == cur_color) {
                Ok = 1;
                ppp = q;
                break;
              }
            if (Ok) {
              if (!marked[i][bg_p]) {
                nnew_save[i][bg_p] = -2;
                ans_count[cur_color]++;
              }
              for (int q = bg_p; q <= en_p; q++) marked[i][q] = 1;
              if (i + 1 < h) {
                int QQ = ppp;
                while (QQ >= 0 && nnew[i + 1][QQ] == cur_color) QQ--;
                QQ++;
                while (QQ < w && nnew[i + 1][QQ] == cur_color) {
                  marked[i + 1][QQ] = 1;
                  QQ++;
                }
              }
            }
          }
          last_j = -1;
        }
      }
  }
  for (int i = 1; i <= color; i++) ans_ind[ans_count[i]]++;
  int prt = 0;
  for (int i = 0; i < MAXN * MAXN; i++)
    for (int j = 0; j < ans_ind[i]; j++) {
      if (prt)
        printf(" %d", i);
      else
        printf("%d", i);
      prt = 1;
    }
  return 0;
}
