Implementing Numpy array addition with broadcasting in C - python

I'm trying to implement Numpy array addition with broadcasting in C. The below code works for arrays with same shape, how do i make it support broadcasting?
I'll read the data for inputs from files via load_data().
typedef struct tensor {
int *data;
int shape[4];
} Tensor;
int main(int argc, char const *argv[]) {
Tensor input_1, input_2, output;
input_1.data = malloc(256 * sizeof(int));
load_data("input_1", input_1.data);
input_1.shape[0] = 1;
input_1.shape[1] = 16;
input_1.shape[2] = 4;
input_1.shape[3] = 4;
input_2.data = malloc(256 * sizeof(int));
load_data("input_2", input_2.data);
input_2.shape[0] = 1;
input_2.shape[1] = 16;
input_2.shape[2] = 1;
input_2.shape[3] = 1;
output.data = malloc(256 * sizeof(int));
output.shape[0] = 1;
output.shape[1] = 16;
output.shape[2] = 4;
output.shape[3] = 4;
int total_elements =
output.shape[0] * output.shape[1] * output.shape[2] * output.shape[3];
// works when shapes are same for both inputs
for (int x = 0; x < output.shape[0]; x++) {
for (int y = 0; y < output.shape[1]; y++) {
for (int z = 0; z < output.shape[2]; z++) {
for (int w = 0; w < output.shape[3]; w++) {
int index =
x * (output.shape[0] * output.shape[1] * output.shape[2]) +
y * (output.shape[0] * output.shape[1]) + z * (output.shape[2]) +
w;
*(output.data + index) =
*(input_1.data + index) + *(input_2.data + index);
}
}
}
}
return 0;
}

Related

PySide2 Qt Surface Example

I would like to reimplement the Qt C++ "Surface" example (Q3DSurface) in PySide2 but QSurfaceDataArray and QSurfaceDataRow are not available.
void SurfaceGraph::fillSqrtSinProxy()
{
float stepX = (sampleMax - sampleMin) / float(sampleCountX - 1);
float stepZ = (sampleMax - sampleMin) / float(sampleCountZ - 1);
QSurfaceDataArray *dataArray = new QSurfaceDataArray;
dataArray->reserve(sampleCountZ);
for (int i = 0 ; i < sampleCountZ ; i++) {
QSurfaceDataRow *newRow = new QSurfaceDataRow(sampleCountX);
// Keep values within range bounds, since just adding step can cause minor drift due
// to the rounding errors.
float z = qMin(sampleMax, (i * stepZ + sampleMin));
int index = 0;
for (int j = 0; j < sampleCountX; j++) {
float x = qMin(sampleMax, (j * stepX + sampleMin));
float R = qSqrt(z * z + x * x) + 0.01f;
float y = (qSin(R) / R + 0.24f) * 1.61f;
(*newRow)[index++].setPosition(QVector3D(x, y, z));
}
*dataArray << newRow;
}
m_sqrtSinProxy->resetArray(dataArray);
}
Is there are way to use a QVector<QSurfaceDataItem> in PySide2?
from PySide2.QtDataVisualization import QtDataVisualization as QDV
data_item = QDV.QSurfaceDataItem()
data_item.setPosition(QVector3D(x, y, z))
The QSurfaceDataItem is available but I can't pass the objects to QSurfaceDataProxy without QVector.

Write a function given a zero-indexed matrix A consisting of N rows and M columns of integers, returns the number of equilibrium points of matrix A

Hey guys I am doing a question where I have to find a point in a Matrix A of N x M rows such that
the sum of rows above the point is equal to the sum of row
Consider this example
/**
* A[0][0] = 2 A[0][1] = 7 A[0][2] = 5
* A[1][0] = 3 A[1][1] = 1 A[1][2] = 1
* A[2][0] = 2 A[2][1] = 1 A[2][2] = -7
* A[3][0] = 0 A[3][1] = 2 A[3][2] = 1
* A[4][0] = 1 A[4][1] = 6 A[4][2] = 8
* #param matrix
* #return
*/
In this example the if we look at the point A[1][1], it can be said that the row above (sum = 14) is equal to the sum of rows below the point. Can anyone help me on this?
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Equilibrium {
private static Logger log = LoggerFactory.getLogger(Equilibrium.class);
public static void main(String[] args) {
int[][] A = new int[][] {
{ 2, 7, 5 },
{ 3, 1, 1 },
{ 2, 1, -7 },
{ 0, 2, 1 },
{ 1, 6, 8 } };
}
private static int solution(int[][] A) {
int[] row = new int[A.length];
int[] column = new int[A[0].length];
int equiRow = 0;
int equiColumn = 0;
int position = 0;
int num = 0;
for (int i = 0; i < row.length; i++) {
for (int j = 0; j < column.length; j++) {
num += A[i][j];
}
row[position++] = num;
num = 0;
}
position = 0;
for (int i = 0; i < column.length; i++) {
for (int j = 0; j < row.length; j++) {
num += A[j][i];
}
column[position++] = num;
num = 0;
}
for (int i = 0; i < row.length; i++) {
int leftsum = 0;
int rightsum = 0; /
for (int j = 0; j < i; j++) {
leftsum += row[j];
}
for (int k = i + 1; k < row.length; k++) {
rightsum += row[k];
}
if (leftsum == rightsum) {
equiRow++;
}
}
for (int i = 0; i < column.length; i++) {
int leftsum = 0;
int rightsum = 0;
for (int j = 0; j < i; j++) {
leftsum += column[j];
}
for (int k = i + 1; k < column.length; k++) {
rightsum += column[k];
}
if (leftsum == rightsum) {
equiColumn++;
}
}
return equiRow * equiColumn;
}
}

optical flow .flo files

I have a few questions for doing optical flow projects. I use Python 2 (planning to use lasagne to use deep learning to learn optical flow), and don't know how to convert the c++ functions to that of python in visualization of the flows.
I downloaded (from http://vision.middlebury.edu/flow/data/comp/zip/other-gt-flow.zip) some image pairs where I have to estimate their optical flow, and their ground truth flow (.flo file). The problem is, when I read the .flo file into the program, it is a vectorized code. How do I view them like how they show in the webpage (http://vision.middlebury.edu/flow/data/)? I read from various sources and tried the following, but doesn't work.
In evaluating EPE (end point error) in what form should I have my prediction to be compared with the .flo file?
The code:
################################ Reading flow file ################################
f = open('flow10.flo', 'rb')
x = np.fromfile(f, np.int32, count=1) # not sure what this gives
w = np.fromfile(f, np.int32, count=1) # width
h = np.fromfile(f, np.int32, count=1) # height
print 'x %d, w %d, h %d flo file' % (x, w, h)
data = np.fromfile(f, np.float32) # vector
data_2D = np.reshape(data, newshape=(388,584,2)); # convert to x,y - flow
x = data_2D[...,0]; y = data_2D[...,1];
################################ visualising flow file ################################
mag, ang = cv2.cartToPolar(x,y)
hsv = np.zeros_like(x)
hsv = np.array([ hsv,hsv,hsv ])
hsv = np.reshape(hsv, (388,584,3)); # having rgb channel
hsv[...,1] = 255; # full green channel
hsv[...,0] = ang*180/np.pi/2 # angle in pi
hsv[...,2] = cv2.normalize(mag,None,0,255,cv2.NORM_MINMAX) # magnitude [0,255]
bgr = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)
bgr = draw_hsv(data_2D)
cv2.imwrite('opticalhsv.png',bgr)
On Middlebury's page there is a zip file called flow-code (http://vision.middlebury.edu/flow/code/flow-code.zip), which provides a tool called color_flow to convert those .flo files to color images.
On the other hand, if you want to implement your own code to do the transformation, i have this piece of code (i cannot provide the original author, it has been some time) that helps you to first compute the color:
static Vec3b computeColor(float fx, float fy)
{
static bool first = true;
// relative lengths of color transitions:
// these are chosen based on perceptual similarity
// (e.g. one can distinguish more shades between red and yellow
// than between yellow and green)
const int RY = 15;
const int YG = 6;
const int GC = 4;
const int CB = 11;
const int BM = 13;
const int MR = 6;
const int NCOLS = RY + YG + GC + CB + BM + MR;
static Vec3i colorWheel[NCOLS];
if (first)
{
int k = 0;
for (int i = 0; i < RY; ++i, ++k)
colorWheel[k] = Vec3i(255, 255 * i / RY, 0);
for (int i = 0; i < YG; ++i, ++k)
colorWheel[k] = Vec3i(255 - 255 * i / YG, 255, 0);
for (int i = 0; i < GC; ++i, ++k)
colorWheel[k] = Vec3i(0, 255, 255 * i / GC);
for (int i = 0; i < CB; ++i, ++k)
colorWheel[k] = Vec3i(0, 255 - 255 * i / CB, 255);
for (int i = 0; i < BM; ++i, ++k)
colorWheel[k] = Vec3i(255 * i / BM, 0, 255);
for (int i = 0; i < MR; ++i, ++k)
colorWheel[k] = Vec3i(255, 0, 255 - 255 * i / MR);
first = false;
}
const float rad = sqrt(fx * fx + fy * fy);
const float a = atan2(-fy, -fx) / (float)CV_PI;
const float fk = (a + 1.0f) / 2.0f * (NCOLS - 1);
const int k0 = static_cast<int>(fk);
const int k1 = (k0 + 1) % NCOLS;
const float f = fk - k0;
Vec3b pix;
for (int b = 0; b < 3; b++)
{
const float col0 = colorWheel[k0][b] / 255.f;
const float col1 = colorWheel[k1][b] / 255.f;
float col = (1 - f) * col0 + f * col1;
if (rad <= 1)
col = 1 - rad * (1 - col); // increase saturation with radius
else
col *= .75; // out of range
pix[2 - b] = static_cast<uchar>(255.f * col);
}
return pix;
}
Then it calls the above function for all the pixels:
static void drawOpticalFlow(const Mat_<Point2f>& flow, Mat& dst, float maxmotion = -1)
{
dst.create(flow.size(), CV_8UC3);
dst.setTo(Scalar::all(0));
// determine motion range:
float maxrad = maxmotion;
if (maxmotion <= 0)
{
maxrad = 1;
for (int y = 0; y < flow.rows; ++y)
{
for (int x = 0; x < flow.cols; ++x)
{
Point2f u = flow(y, x);
if (!isFlowCorrect(u))
continue;
maxrad = max(maxrad, sqrt(u.x * u.x + u.y * u.y));
}
}
}
for (int y = 0; y < flow.rows; ++y)
{
for (int x = 0; x < flow.cols; ++x)
{
Point2f u = flow(y, x);
if (isFlowCorrect(u))
dst.at<Vec3b>(y, x) = computeColor(u.x / maxrad, u.y / maxrad);
}
}
}
This is for my use in OpenCV, but the code help should anyone who wants achieve something similar.

Calculating feature vectors for image segments (super-pixels)

For tasks like clustering or classification on images we generally convert images to numerical feature vectors. Now, instead of calculating feature vectors for an entire image, I would like to generate features for segments of an image (not constrained to rectangular segments). For example, using the SLIC algorithm (skimage.segmentation.slic) I can segment an image into super pixels. Now I would like to generate features (region size, location, color, shape and texture features) for each segment as described in section 5.3 of
Gould, Stephen, et al. "Multi-class segmentation with relative location prior." International Journal of Computer Vision 80.3 (2008): 300-316.
Are there existing libraries in python that can help me generate those features, given an image and a mask of segments? Can I do this using skimage?
I am not aware of any such library. However, I needed to compute features myself some time ago and you can find some code snippets below. Although, the code is not in Python, it might be helpful for you. Note that I experimented with supervoxels; therefore, you may find some PCL reference in there.
If you start implementing features yourself, have a look at the following publications for some ideas (in both cases Table 1):
Derek Hoiem, Andrew N. Stein, Alexei A. Efros, Martial Hebert:
Recovering Occlusion Boundaries from a Single Image. ICCV 2007: 1-8
Joseph Tighe, Svetlana Lazebnik:
Superparsing - Scalable Nonparametric Image Parsing with Superpixels. International Journal of Computer Vision 101(2): 329-349 (2013)
Note that not all definitions from the header file are actually implemented; however, they may serve as inspiration.
Header:
#ifndef SUPERPIXELFEATURES_H
#define SUPERPIXELFEATURES_H
#include <opencv2/opencv.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <Eigen/Dense>
#include <string>
namespace features {
/**
* Class SuperpixelFeatures represents a set of features computed for
* each superpixel in a given image.
*/
class SuperpixelFeatures {
public:
/**
* Construct superpixel features form only an image.
*
* #param image
* #param labels
*/
SuperpixelFeatures(const cv::Mat &image, int** labels);
/**
* Construct superpixel features from the image and its depth and
* a given superpixel segmentation.
*
* #param image
* #param depth
* #param labels
*/
SuperpixelFeatures(const cv::Mat &image, const cv::Mat &depth, int** labels);
/**
* Constructu superpixel features form the image and a point cloud and
* a given superpixel segmentation.
*
* #param image
* #param pointCloud
*/
SuperpixelFeatures(const cv::Mat &image, pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud, int** labels);
/**
* Destructor.
*/
~SuperpixelFeatures();
/**
* Add maximum color in each channel to the features.
*
* #return
*/
Eigen::Vector2i addMaximumColor();
/**
* Add minimum color in each channel to the features.
*
* #return
*/
Eigen::Vector2i addMinimumColor();
/**
* Add mean color to the features.
*
* #return
*/
Eigen::Vector2i addMeanBGRColor();
/**
* Add mean position to the features.
*
* #return
*/
Eigen::Vector2i addMean3DPosition();
/**
* Add mean position (pixel coordinates) to the features.
*
* #return
*/
Eigen::Vector2i addMean2DPosition();
/**
* Add the surface normal (mean normal) to the features.
*
* #return
*/
Eigen::Vector2i addMeanNormal();
/**
* Add a 3D bounding box of the superpixel to the features.
*
* #return
*/
Eigen::Vector2i addBoundingBox();
/**
* Add the compactness of the superpixel in its 2D sens to the features.
*
* #return
*/
Eigen::Vector2i addCompactness();
/**
* Add the area in pixels to the features.
*
* #return
*/
Eigen::Vector2i addArea();
/**
* Add the color covariance matrix to the features.
*
* #return
*/
Eigen::Vector2i addColorCovariance();
/**
* Add the position covariance matrix to the features.
* #return
*/
Eigen::Vector2i addPositionCovariance();
/**
* Add point-ness, curve-ness and surface-ness to the features.
*
* #return
*/
Eigen::Vector2i addSuperpixelStatistics();
/**
* Add a color histogram of the given number of bins to the features.
*
* #param bins
* #return
*/
Eigen::Vector2i addColorHistogram(int bins);
/**
* Add the ground truth label to the features.
*
* #param labels
* #return
*/
Eigen::Vector2i addGroundTruth(int** labels);
/**
* Get the dimension of the computed features.
*
* #return
*/
int getFeatureDimension() const;
/**
* Get the total number of superpixels.
*
* #return
*/
int getNumberOfSuperpixels() const;
/**
* Get pointer to comptued features.
*
* #return
*/
Eigen::MatrixXd* getFeatures() const;
protected:
void appendFeatures(Eigen::MatrixXd features);
cv::Mat* image;
int height;
int width;
int** labels;
int numberOfSuperpixels;
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud;
bool pointCloudAvailable;
Eigen::MatrixXd* features;
};
}
Source:
#include <pcl/features/normal_3d.h>
#include <pcl/features/integral_image_normal.h>
#include "Tools.h"
#include "SuperpixelFeatures.h"
SuperpixelFeatures::SuperpixelFeatures(const cv::Mat &image, int** labels) {
this->image = new cv::Mat();
int channels = image.channels();
assert(channels == 1 || channels == 3);
if (channels == 1) {
image.convertTo(*this->image, CV_8UC1);
}
else if (channels == 3) {
image.convertTo(*this->image, CV_8UC3);
cv::cvtColor(*this->image, *this->image, SEEDS_REVISED_OPENCV_BGR2Lab, 3);
}
this->height = image.rows;
this->width = image.cols;
this->pointCloudAvailable = false;
// Copy labels.
this->labels = new int*[this->height];
for (int i = 0; i < this->height; ++i) {
this->labels[i] = new int[this->width];
for (int j = 0; j < this->width; ++j) {
this->labels[i][j] = labels[i][j];
}
}
this->numberOfSuperpixels = seeds_revised::tools::Integrity::countSuperpixels(this->labels, this->height, this->width);
seeds_revised::tools::Integrity::relabel(this->labels, this->height, this->width);
this->features = new Eigen::MatrixXd(this->numberOfSuperpixels, 1);
// Initialize first column with labels.
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
(*this->features)(label, 0) = label;
}
}
SuperpixelFeatures::SuperpixelFeatures(const cv::Mat &image, pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloud, int** labels) {
assert(image.rows == (int) pointCloud->height);
assert(image.cols == (int) pointCloud->width);
this->image = new cv::Mat();
int channels = image.channels();
assert(channels == 1 || channels == 3);
if (channels == 1) {
image.convertTo(*this->image, CV_8UC1);
}
else if (channels == 3) {
image.convertTo(*this->image, CV_8UC3);
cv::cvtColor(*this->image, *this->image, SEEDS_REVISED_OPENCV_BGR2Lab, 3);
}
this->pointCloud = pointCloud;
this->height = pointCloud->height;
this->width = pointCloud->width;
this->pointCloudAvailable = true;
// Copy labels.
this->labels = new int*[this->height];
for (int i = 0; i < this->height; ++i) {
this->labels[i] = new int[this->width];
for (int j = 0; j < this->width; ++j) {
this->labels[i][j] = labels[i][j];
}
}
this->numberOfSuperpixels = seeds_revised::tools::Integrity::countSuperpixels(this->labels, this->height, this->width);
seeds_revised::tools::Integrity::relabel(this->labels, this->height, this->width);
this->features = new Eigen::MatrixXd(this->numberOfSuperpixels, 1);
// Initialize first column with labels.
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
(*this->features)(label, 0) = label;
}
}
SuperpixelFeatures::~SuperpixelFeatures() {
delete this->image;
for (int i = 0; i < this->height; ++i) {
delete[] this->labels[i];
}
delete[] this->labels;
}
Eigen::Vector2i SuperpixelFeatures::addMeanBGRColor() {
int cols = this->features->cols();
this->features->resize(this->numberOfSuperpixels, cols + 3);
double meanB = 0;
double meanG = 0;
double meanR = 0;
int count = 0;
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
meanB = 0;
meanG = 0;
meanR = 0;
count = 0;
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
if (this->labels[i][j] == label) {
meanB += this->image->at<cv::Vec3b>(i, j)[0];
meanG += this->image->at<cv::Vec3b>(i, j)[1];
meanR += this->image->at<cv::Vec3b>(i, j)[2];
++count;
}
}
}
(*this->features)(label, cols) = meanB/count;
(*this->features)(label, cols + 1) = meanG/count;
(*this->features)(label, cols + 2) = meanR/count;
}
return Eigen::Vector2i(cols, cols + 2);
}
Eigen::Vector2i SuperpixelFeatures::addMean3DPosition() {
assert(this->pointCloudAvailable);
int cols = this->features->cols();
this->features->resize(this->numberOfSuperpixels, cols + 3);
double meanX = 0;
double meanY = 0;
double meanZ = 0;
int count = 0;
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
meanX = 0;
meanY = 0;
meanZ = 0;
count = 0;
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
if (this->labels[i][j] == label) {
meanX += (*this->pointCloud)(j, i).x;
meanY += (*this->pointCloud)(j, i).y;
meanZ += (*this->pointCloud)(j, i).z;
++count;
}
}
}
(*this->features)(label, cols) = meanX/count;
(*this->features)(label, cols + 1) = meanY/count;
(*this->features)(label, cols + 2) = meanZ/count;
}
return Eigen::Vector2i(cols, cols + 2);
}
Eigen::Vector2i SuperpixelFeatures::addMean2DPosition() {
int cols = this->features->cols();
this->features->resize(this->numberOfSuperpixels, cols + 2);
double meanX = 0;
double meanY = 0;
int count = 0;
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
meanX = 0;
meanY = 0;
count = 0;
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
if (this->labels[i][j] == label) {
meanX += j;
meanY += i;
++count;
}
}
}
(*this->features)(label, cols) = meanX/count;
(*this->features)(label, cols + 1) = meanY/count;
}
return Eigen::Vector2i(cols, cols + 1);
}
Eigen::Vector2i SuperpixelFeatures::addMeanNormal() {
int cols = this->features->cols();
this->features->resize(this->numberOfSuperpixels, cols + 3);
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
std::vector<int> indices;
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
if (this->labels[i][j] == label) {
indices.push_back(i*cols + j);
}
}
}
Eigen::Vector4f superpixelCentroid;
Eigen::Matrix3f superpixelCovariance;
Eigen::Vector3f superpixelNormal;
pcl::compute3DCentroid(*pointCloud, indices, superpixelCentroid);
pcl::computeCovarianceMatrix(*pointCloud, indices, superpixelCentroid, superpixelCovariance);
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> superpixelEigenValues(superpixelCovariance);
superpixelNormal = superpixelEigenValues.eigenvectors().col(0);
(*this->features)(label, cols) = superpixelNormal(0);
(*this->features)(label, cols + 1) = superpixelNormal(1);
(*this->features)(label, cols + 2) = superpixelNormal(2);
}
return Eigen::Vector2i(cols, cols + 2);
}
Eigen::Vector2i SuperpixelFeatures::addArea() {
int cols = this->features->cols();
this->features->resize(this->numberOfSuperpixels, cols + 1);
int area = 0;
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
area = 0;
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
if (this->labels[i][j] == label) {
++area;
}
}
}
(*this->features)(label, cols) = area;
}
return Eigen::Vector2i(cols, cols);
}
Eigen::Vector2i SuperpixelFeatures::addSuperpixelStatistics() {
assert(this->pointCloudAvailable);
int cols = this->features->cols();
this->features->resize(this->numberOfSuperpixels, cols + 3);
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
std::vector<int> indices;
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
if (this->labels[i][j] == label) {
indices.push_back(i*cols + j);
}
}
}
Eigen::Vector4f superpixelCentroid;
Eigen::Matrix3f superpixelCovariance;
Eigen::Vector3f superpixelNormal;
pcl::compute3DCentroid(*pointCloud, indices, superpixelCentroid);
pcl::computeCovarianceMatrix(*pointCloud, indices, superpixelCentroid, superpixelCovariance);
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> superpixelEigenValues(superpixelCovariance);
// Point-ness:
(*this->features)(label, cols) = superpixelEigenValues.eigenvalues()(0);
(*this->features)(label, cols + 1) = superpixelEigenValues.eigenvalues()(2) - superpixelEigenValues.eigenvalues()(1);
(*this->features)(label, cols + 2) = superpixelEigenValues.eigenvalues()(1) - superpixelEigenValues.eigenvalues()(0);
}
return Eigen::Vector2i(cols, cols + 2);
}
Eigen::Vector2i SuperpixelFeatures::addColorHistogram(int bins) {
assert(bins > 0 && bins < 10);
int histogramSize = std::pow(bins, 3);
int cols = this->features->cols();
this->features->resize(this->numberOfSuperpixels, cols + histogramSize);
int* normalization = new int[this->numberOfSuperpixels];
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
normalization[label] = 0;
for (int k = 0; k < histogramSize; ++k) {
(*this->features)(label, cols + k) = 0;
}
}
int denominator = ceil(256./((double) bins));
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
int bin = this->image->at<cv::Vec3b>(i, j)[0]/denominator + bins*(this->image->at<cv::Vec3b>(i, j)[1]/denominator) + bins*bins*(this->image->at<cv::Vec3b>(i, j)[2]/denominator);
++(*this->features)(this->labels[i][j], cols + bin);
++normalization[this->labels[i][j]];
}
}
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
for (int k = 0; k < histogramSize; ++k) {
(*this->features)(label, cols + k) /= normalization[label];
}
}
return Eigen::Vector2i(cols, cols + histogramSize);
}
Eigen::Vector2i SuperpixelFeatures::addGroundTruth(int** labels) {
int numberOfLabels = 0;
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
if (labels[i][j] > numberOfLabels) {
numberOfLabels = labels[i][j];
}
}
}
// Remember that zero may be a label as well.
numberOfLabels = numberOfLabels + 1;
Eigen::MatrixXi intersection(this->numberOfSuperpixels, numberOfLabels);
for (int i = 0; i < this->height; ++i) {
for (int j = 0; j < this->width; ++j) {
assert(this->labels[i][j] < this->numberOfSuperpixels);
assert(labels[i][j] < numberOfLabels);
++intersection(this->labels[i][j], labels[i][j]);
}
}
for (int label = 0; label < this->numberOfSuperpixels; ++label) {
int maxIntersection = 0;
int maxGTLabel = 0;
for (int gtLabel = 0; gtLabel < numberOfLabels; ++gtLabel) {
if (intersection(label, gtLabel) > maxIntersection) {
maxIntersection = intersection(label, gtLabel);
maxGTLabel = gtLabel;
}
}
(*this->features)(label, 0) = maxGTLabel;
}
return Eigen::Vector2i(0, 0);
}
int SuperpixelFeatures::getFeatureDimension() const {
return this->features->cols();
}
Eigen::MatrixXd* SuperpixelFeatures::getFeatures() const {
return this->features;
}
For python I'd recommend using fast_slic which is WICKED fast despite only using a CPU. As for accessing the individual segments try reading over Adrian Rosebrock's tutorial on PyImageSearch and using a bounding box algorithm to find the specific roi you're interested in. If your work needs only the image itself and no zero padding, then you can try sklearn.feature_extraction.image.extract_patches_2d along with a condition to only retain image patches that do not have zeros across the channels.

Exceed the maximum recursion depth

I am doing a connected component operation on images: all of the pixels which are connected and have the same value will be assigned the same label.
An example is that if the input is:
1 1 2 2
2 4 4 1
1 5 1 1
it should return:
1 1 2 2
3 4 4 5
6 7 5 5
Two blobs which have value 1 has been reassigned to 1 and 5.
This code works for small images. But when applying to larger one (512x512), it usually reach the maximum number of recursive stack allowed (Python, Visual Studio C++ but not gcc C++). How to fix the problem?
vector<int> neighbors(int pixel, int height, int width)
// return neighboring pixels
{
assert(pixel < height *width);
vector<int> indexes;
if (pixel % width == width - 1)
{
indexes.push_back(pixel - 1);
indexes.push_back(pixel - width);
indexes.push_back(pixel + width);
}
else if (pixel % width == 0)
{
indexes.push_back(pixel + 1);
indexes.push_back(pixel - width);
indexes.push_back(pixel + width);
}
else
{
indexes.push_back(pixel + 1);
indexes.push_back(pixel - 1);
indexes.push_back(pixel - width);
indexes.push_back(pixel + width);
}
vector<int> out;
for(int i = 0; i < indexes.size(); i++)
{
if (indexes[i] >= 0 && indexes[i] < height*width)
out.push_back(indexes[i]);
}
return out;
}
void floodfill(const unsigned char *im, unsigned char *out, int pixel, int height, int width, int label)
// starting from the pixel, label all connected labels to pixel
{
if (*(out + pixel) == 0)
{
*(out + pixel) = label;
vector<int> ns = neighbors(pixel, height, width);
for(int i = 0; i < ns.size(); i++)
{
if ((*(out + ns[i]) == 0) && *(im + ns[i]) == *(im + pixel))
{
floodfill(im, out, ns[i], height, width, label);
}
}
}
}
int ConnectedComponent(const unsigned char *im, unsigned char *out, int height, int width)
{
for (int i = 0; i < height*width; i++)
*(out+i) = 0;
int label = 0;
for (int i = 0; i < height *width; i++)
{
if (*(out + i) == 0)
{
label++;
floodfill(lev, out, i, height, width, label);
}
}
return label;
}
Testing code is:
TEST(testLulu, connectedcomponenet)
{
unsigned char lev[12] = {1,1,2,2,2,4,4,1,1,5,1,1};
unsigned char * out = new unsigned char[12]();
ConnectedComponent(lev, out, 3,4);
unsigned char correct[12] = {1,1,2,2,3,4,4,5,6,7,5,5};
for (int i = 0; i<12; i++)
{
EXPECT_EQ(correct[i], out[i]);
}
}

Categories

Resources