static int lu_solve(lud_type *s, mat_op_type o, matrix_type *m) { return vsip_clusol_f(s, mat_op(o), m);}
static int qr_solve_r(qr_type *qr, mat_op_type o, float t, matrix_type *m) { return vsip_qrdsolr_f(qr, mat_op(o), t, m);}
static int qr_prodq(qr_type *qr, mat_op_type o, product_side_type s, matrix_type *m) { return vsip_qrdprodq_f(qr, mat_op(o), product_side(s), m); }
static int qr_solve_r(qr_type *qr, mat_op_type o, std::complex<double> t, matrix_type *m) { vsip_cscalar_d tt = {t.real(), t.imag()}; return vsip_cqrdsolr_d(qr, mat_op(o), tt, m); }
static int qr_solve_r(qr_type *qr, mat_op_type o, double t, matrix_type *m) { return vsip_qrdsolr_d(qr, mat_op(o), t, m);}
ushort find_thresh(num* vhist, num lbound, num ubound, num no_iters) { ar("ohist", vhist, 256); num mu1_o = lbound, mu2_o = ubound; num prb1_o = 1.0/2.0, prb2_o = 1.0/2.0; num seg1_o = 10.0, seg2_o = 10.0; num dclass1[255]; num dclass2[255]; num x_image[255]; num result[255]; for (ushort it=0; it < 255; ++it) { x_image[it] = it; } for (ushort it=0; it < 100; ++it) { for (ushort i=0; i < 255; ++i) { num pclass1, pclass2, psum, pc1s, pc2s; pclass1 = gauss(i, mu1_o, seg1_o); pclass2 = gauss(i, mu2_o, seg2_o); pc1s = prb1_o * pclass1; pc2s = prb2_o * pclass2; psum = pc1s + pc2s; if (psum == 0) { dclass1[i] = NUM_EPSILON; dclass2[i] = NUM_EPSILON; } else { dclass1[i] = vhist[i] * (pc1s / psum); dclass2[i] = vhist[i] * (pc2s / psum); } } num sum_dc1, sum_dc2; sum_dc1 = sum_of(dclass1, 255); sum_dc2 = sum_of(dclass2, 255); prb1_o = sum_dc1 / 255; prb2_o = sum_dc2 / 255; mat_op(dclass1, x_image, 255, mul, result); mu1_o = sum_of(result, 255) / sum_dc1; mat_op(dclass2, x_image, 255, mul, result); mu2_o = sum_of(result, 255) / sum_dc2; mat_op(x_image, mu1_o, 255, sub, result); mat_op(result, 2, 255, pown, result); mat_op(result, dclass1, 255, mul, result); seg1_o = sum_of(result, 255) / sum_dc1; mat_op(x_image, mu2_o, 255, sub, result); mat_op(result, 2, 255, pown, result); mat_op(result, dclass1, 255, mul, result); seg2_o = sum_of(result, 255) / sum_dc2; prb1_o /= (prb1_o + prb2_o); prb2_o /= (prb1_o + prb2_o); } prb1_o /= (prb1_o + prb2_o); prb2_o /= (prb1_o + prb2_o); num dgauss1[255]; num dgauss2[255]; num aconst, bconst; for (ushort k=0; k < 255; ++k) { aconst = 1 / sqrt(2 * PI * seg1_o); bconst = square(k - 1 - mu1_o) / (2 * seg1_o); dgauss1[k] = prb1_o * aconst * exp(-bconst); aconst = 1 / sqrt(2 * PI * seg2_o); bconst = square(k - 1 - mu2_o) / (2 * seg2_o); dgauss2[k] = prb2_o * aconst * exp(-bconst); } num destimate[255]; mat_op(dgauss1, dgauss2, 255, add, destimate); mat_op(destimate, sum_of(destimate, 255), 255, divn, destimate); num error[255]; mat_op(vhist, destimate, 255, sub, error); ar("destimate", destimate, 255); ar("derror", error, 255); num sign_error[255]; m_apply(error, sign, 255, sign_error); vector<num> positions(1, 0); for (short k=0; k < 254; ++k) { if (sign_error[k] != sign_error[k+1]) { positions.push_back(k); } } positions.push_back(255); vector<num> init_mu; for (ushort k=0; k < positions.size() - 1; ++k) { if (positions[k + 1] - positions[k] > 1) { init_mu.push_back((positions[k + 1] + positions[k]) / 2.0); } } m_apply(error, abs, 255, result); num constant = sum_of(result, 255); num model[255]; mat_op(result, constant, 255, divn, model); ar("absolute error model", model, 255); num num_gauss = init_mu.size(); num** pdf = new num*[(ushort) num_gauss]; for (ushort k=0; k < num_gauss; ++k) { pdf[k] = new num[255]; } ar("posn vec: ", positions, positions.size()); ar("init_mu: pre gen_em", init_mu, (uint) num_gauss); general_em(model, init_mu, x_image, no_iters, num_gauss, pdf); ar("init_mu: post gen_em", init_mu, (uint) num_gauss); ushort t1 = lbound; while (dgauss1[t1] > dgauss2[t1]) { ++t1; } // result = const .* sign(error) mat_op(sign_error, constant, 255, mul, result); for (ushort k=0; k < 2 /* num_gauss */; ++k) { mat_op(result, pdf[k], 255, mul, error); if (init_mu[k] < (t1 + 10)) { mat_op(dgauss1, error, 255, add, dgauss1); } else { mat_op(dgauss2, error, 255, add, dgauss2); } } m_apply(dgauss1, abs, 255, dgauss1); m_apply(dgauss2, abs, 255, dgauss2); t1 = lbound; while (dgauss1[t1] > dgauss2[t1]) { ++t1; } del_num_table(pdf, (uint) num_gauss); return t1; }
void general_em(num* model, vector<num>& init_mu, num* x_image, ushort iters, num num_gauss, num** pdf) { num* variance = new num[(ushort) num_gauss]; num* prob = new num[(ushort) num_gauss]; num* P = new num[(ushort) num_gauss]; num* A = new num[(ushort) num_gauss]; // result arrays for data of fixed lengths num* result_ng = new num[(ushort) num_gauss]; num result_255[255]; num** dclass = new num*[(ushort) num_gauss]; for (ushort k=0; k < num_gauss; ++k) { dclass[k] = new num[255]; variance[k] = 20; prob[k] = 1 / num_gauss; P[k] = NUM_EPSILON; } for (ushort k=0; k < iters; ++k) { for (ushort i=0; i < 255; ++i) { for (ushort k2=0; k2 < num_gauss; ++k2) { P[k2] = gauss(i, init_mu[k2], variance[k2]); } mat_op(P, prob, (uint) num_gauss, mul, result_ng); num sum_p_prob = sum_of(result_ng, (uint) num_gauss); for (ushort k2=0; k2 < num_gauss; ++k2) { dclass[k2][i] = sum_p_prob ? ((prob[k2] * P[k2]) / sum_p_prob) * model[i] : NUM_EPSILON; } } for (ushort k2=0; k2 < num_gauss; ++k2) { num temp = sum_of(dclass[k2], 255); A[k2] = temp / 255; mat_op(dclass[k2], x_image, 255, mul, result_255); init_mu[k2] = sum_of(result_255, 255) / temp; mat_op(x_image, init_mu[k2], 255, sub, result_255); mat_op(result_255, 2, 255, pown, result_255); mat_op(dclass[k2], result_255, 255, mul, result_255); variance[k2] = sum_of(result_255, 255) / temp; } num sum_a = sum_of(A, (uint) num_gauss); for (ushort k2=0; k2 < num_gauss; ++k2) { prob[k2] = A[k2] / sum_a; } } for (ushort k2=0; k2 < num_gauss; ++k2) { for (ushort k=0; k < 255; ++k) { num aconst, bconst; aconst = 1 / sqrt(2 * PI * variance[k2]); bconst = square(k - 1 - init_mu[k2]) / (2 * variance[k2]); pdf[k2][k] = prob[k2] * aconst * exp(-bconst); } } del_num_table(dclass, (uint) num_gauss); delete[] variance; delete[] prob; delete[] P; delete[] A; delete[] result_ng; }
static void process_region(img** volume, img** orig, ushort thresh, vector<ushort>& rar, vector<ushort>& car, vector<ushort>& zar) { static num dmap[6][512][512]; // if the region is too small... if (rar.size() < 600) { cout << "--> deleted an unlikely region (size: " << rar.size() << ")\n"; return; } // if the region spans too many slices vertically... int region_zmin = *min_element(zar.begin(), zar.end()); if (*max_element(zar.begin(), zar.end()) - region_zmin > 5) { dp("--> deleted an unlikely region (z-interval > 5)"); return; } // find the boundary of the region vector<ushort> edge_rar, edge_car, edge_zar; for (ushort i=0; i < zar.size(); ++i) { for (ushort q=zar[i]-1; q < zar[i]+2; ++q) { for (ushort k=rar[i]-1; k < rar[i]+2; ++k) { for (ushort j=car[i]-1; j < car[i]+2; ++j) { if (volume[q]->pix[k][j] == white) { edge_rar.push_back(rar[i]); edge_car.push_back(car[i]); edge_zar.push_back(zar[i]); volume[zar[i]]->pix[rar[i]][car[i]] = 0; break; } } if (volume[zar[i]]->pix[rar[i]][car[i]] == 0) { break; } } if (volume[zar[i]]->pix[rar[i]][car[i]] == 0) { break; } } } ar("--> region-boundary z-vec", edge_zar, edge_zar.size()); // create a distance map uint blen = edge_rar.size(); num *erar, *ecar, *ezar, *dvec, *tmp; try { erar = new num[blen]; ecar = new num[blen]; ezar = new num[blen]; dvec = new num[blen]; tmp = new num[blen]; } catch (bad_alloc& err) { dp("Fatal memory allocation error; results may be unreliable!"); return; } for (uint i=0; i < blen; ++i) { // copy the boundary voxels into num-arrays to make things simple erar[i] = (num) edge_rar[i]; ecar[i] = (num) edge_car[i]; ezar[i] = (num) edge_zar[i]; } // find the minimum distance from the boundary for each point for (uint i=0; i < zar.size(); ++i) { mat_op(erar, (num) rar[i], blen, sub, tmp); mat_op(tmp, dx, blen, mul, tmp); m_apply(tmp, square, blen, dvec); mat_op(ecar, (num) car[i], blen, sub, tmp); mat_op(tmp, dy, blen, mul, tmp); m_apply(tmp, square, blen, tmp); mat_op(tmp, dvec, blen, add, dvec); mat_op(ezar, (num) zar[i], blen, sub, tmp); mat_op(tmp, dz, blen, mul, tmp); m_apply(tmp, square, blen, tmp); mat_op(tmp, dvec, blen, add, dvec); m_apply(dvec, sqrt, blen, dvec); // store the distance into the distance map dmap[zar[i] - region_zmin][rar[i]][car[i]] = *min_element(dvec, dvec+blen); } // find the 'centroid' of the region num cen_max = 0; ushort cenz=0, cenx=0, ceny=0; for (ushort i=0; i < zar.size(); ++i) { num cur_val = dmap[zar[i] - region_zmin][rar[i]][car[i]]; if (cur_val > cen_max) { cen_max = cur_val; cenz = zar[i] - region_zmin; cenx = rar[i]; ceny = car[i]; } } cout << "--> region centroid: [" << cenx << ", " << ceny << ", " << region_zmin + cenz << "]\n"; // find the variance of the distance from the boundary to the centroid for (ushort i=0; i < blen; ++i) { tmp[i] = sqrt(square((erar[i] - cenx) * dx) + square((ecar[i] - ceny) * dy) + square((ezar[i] - cenz) * dz)); } num edge_u = sum_of(tmp, blen) / blen; mat_op(tmp, edge_u, blen, sub, tmp); m_apply(tmp, square, blen, tmp); num stddev = sqrt(sum_of(tmp, blen) / blen); cout << "--> (stddev, mean) distance from centroid: (" << stddev << ", " << edge_u << ")\n"; /* My thinking is that 85% or more of the distances should lie within 3 to * 7 units of the mean distance to have a sphere (roughly). According to * Chebyshev's rule [p = 1 - k^-2 => k = sqrt(1 / (1 - p))], 85% of the * distances should lie within 2.582 standard deviations of the mean * distance. So to be spherical, 3 < u - [u - (2.582 * stddev)] < 7. */ num dist_delta = edge_u - (edge_u - (CHEBY_DELTA * stddev)); bool tumor = (dist_delta > 3) && (dist_delta < 7); cout << "--> dist_delta: " << dist_delta << endl; cout << "--> size: " << rar.size() << endl; if (tumor) { uint64_t sum_shade = 0; for (uint i=0; i < zar.size(); ++i) { sum_shade += orig[zar[i]]->pix[rar[i]][car[i]]; } tumor = (sum_shade / zar.size()) > thresh; // 67% empirically } for (uint i=0; i < zar.size(); ++i) { volume[zar[i]]->pix[rar[i]][car[i]] = tumor ? 1 : BENIGN; } cout << "--> " << tumor << " tumor.\n"; delete[] dvec; delete[] tmp; delete[] erar; delete[] ecar; delete[] ezar; }