Library for reading sensor data on Raspberry pi - python
I've been playing around with the GPIO pins on my Raspberry pi recently. While trying out a temperature sensor (the DHT11 specifically) and trying to find some code to get it work, i noticed something that seems kind of weird to me. All the code i found is either using libraries specific to the kind of sensor
Like with this python code:
import sys
import Adafruit_DHT
while True:
humidity, temperature = Adafruit_DHT.read_retry(11, 4)
print 'Temp: {0:0.1f} C Humidity: {1:0.1f} %'.format(temperature, humidity)
Or implementing it completely from scratch like this c-code:
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define MAXTIMINGS 85
#define DHTPIN 7
int dht11_dat[5] = { 0, 0, 0, 0, 0 };
void read_dht11_dat()
{
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0, i;
float f;
dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
pinMode( DHTPIN, OUTPUT );
digitalWrite( DHTPIN, LOW );
delay( 18 );
digitalWrite( DHTPIN, HIGH );
delayMicroseconds( 40 );
pinMode( DHTPIN, INPUT );
for ( i = 0; i < MAXTIMINGS; i++ )
{
counter = 0;
while ( digitalRead( DHTPIN ) == laststate )
{
counter++;
delayMicroseconds( 1 );
if ( counter == 255 )
{
break;
}
}
laststate = digitalRead( DHTPIN );
if ( counter == 255 )
break;
if ( (i >= 4) && (i % 2 == 0) )
{
dht11_dat[j / 8] <<= 1;
if ( counter > 16 )
dht11_dat[j / 8] |= 1;
j++;
}
}
if ( (j >= 40) &&
(dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) )
{
f = dht11_dat[2] * 9. / 5. + 32;
printf( "Humidity = %d.%d %% Temperature = %d.%d C (%.1f F)\n",
dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
}else {
printf( "Data not good, skip\n" );
}
}
int main( void )
{
printf( "Raspberry Pi wiringPi DHT11 Temperature test program\n" );
if ( wiringPiSetup() == -1 )
exit( 1 );
while ( 1 )
{
read_dht11_dat();
delay( 1000 );
}
return(0);
}
So i was wondering why there is no c-library that just returns the raw data read from a specific pin for all kind of sensors
Basically taking over this part:
void read_dht11_dat()
{
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0, i;
float f;
dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
pinMode( DHTPIN, OUTPUT );
digitalWrite( DHTPIN, LOW );
delay( 18 );
digitalWrite( DHTPIN, HIGH );
delayMicroseconds( 40 );
pinMode( DHTPIN, INPUT );
for ( i = 0; i < MAXTIMINGS; i++ )
{
counter = 0;
while ( digitalRead( DHTPIN ) == laststate )
{
counter++;
delayMicroseconds( 1 );
if ( counter == 255 )
{
break;
}
}
laststate = digitalRead( DHTPIN );
if ( counter == 255 )
break;
if ( (i >= 4) && (i % 2 == 0) )
{
dht11_dat[j / 8] <<= 1;
if ( counter > 16 )
dht11_dat[j / 8] |= 1;
j++;
}
}
if ( (j >= 40) &&
(dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) )
{
f = dht11_dat[2] * 9. / 5. + 32;
printf( "Humidity = %d.%d %% Temperature = %d.%d C (%.1f F)\n",
dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3], f );
}else {
printf( "Data not good, skip\n" );
}
}
Why is that ?
First of all, you need to know that the temperature sensor communicates the data via a single GPIO pin, which can be HIGH or LOW. The temperature data for this sensor consist of 5 bytes each. This 5 bytes will stored in dht11_dat array:
dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
So 5 x 8 (40) signals must be received until the temperature data is complete.
The bytes are composed of these individual bits here:
if ( (i >= 4) && (i % 2 == 0) )
{
dht11_dat[j / 8] <<= 1;
if ( counter > 16 )
dht11_dat[j / 8] |= 1;
j++;
}
The last byte is only a checksum for correct communication and will be checked here:
if ( (j >= 40) &&
(dht11_dat[4] == ( (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF) ) )
{
The temperature value in Celcius is stored in byte 3 and 4:
dht11_dat[2], dht11_dat[3]
Related
cv2.estimateRigidTransform minimal number of points?
What is minimal number of points needed for cv2.estimateRigidTransform? As I understand with fullAffine=False it have 4 degrees of freedom, so 2 points should be sufficient. However: Using 2 numpy array as input: src_pts_subset.shape (2, 2) tgt_pts_subset.shape (2, 2) type(src_pts_subset) <class 'numpy.ndarray'> type(tgt_pts_subset) <class 'numpy.ndarray'> src_pts_subset.dtype int64 tgt_pts_subset.dtype int64 To m = cv2.estimateRigidTransform(src_pts, tgt_pts, fullAffine=False) Gives me None.
Theoretically only 2 pair points is needed for non-full affine setting as explained thoroughly by ngia ho. However, upon inspection to the source code in openCV, a minimum of 3 pair points is required for the function to return a value calculated by RANSAC. I have included the corresponding function below for your reference. It is located in the file lkpyramid.cpp in the openCV source file. cv::Mat cv::estimateRigidTransform( InputArray src1, InputArray src2, bool fullAffine ) { return estimateRigidTransform(src1, src2, fullAffine, 500, 0.5, 3); } cv::Mat cv::estimateRigidTransform( InputArray src1, InputArray src2, bool fullAffine, int ransacMaxIters, double ransacGoodRatio, const int ransacSize0) { CV_INSTRUMENT_REGION() Mat M(2, 3, CV_64F), A = src1.getMat(), B = src2.getMat(); const int COUNT = 15; const int WIDTH = 160, HEIGHT = 120; std::vector<Point2f> pA, pB; std::vector<int> good_idx; std::vector<uchar> status; double scale = 1.; int i, j, k, k1; RNG rng((uint64)-1); int good_count = 0; if( ransacSize0 < 3 ) CV_Error( Error::StsBadArg, "ransacSize0 should have value bigger than 2."); if( ransacGoodRatio > 1 || ransacGoodRatio < 0) CV_Error( Error::StsBadArg, "ransacGoodRatio should have value between 0 and 1"); if( A.size() != B.size() ) CV_Error( Error::StsUnmatchedSizes, "Both input images must have the same size" ); if( A.type() != B.type() ) CV_Error( Error::StsUnmatchedFormats, "Both input images must have the same data type" ); int count = A.checkVector(2); if( count > 0 ) { A.reshape(2, count).convertTo(pA, CV_32F); B.reshape(2, count).convertTo(pB, CV_32F); } else if( A.depth() == CV_8U ) { int cn = A.channels(); CV_Assert( cn == 1 || cn == 3 || cn == 4 ); Size sz0 = A.size(); Size sz1(WIDTH, HEIGHT); scale = std::max(1., std::max( (double)sz1.width/sz0.width, (double)sz1.height/sz0.height )); sz1.width = cvRound( sz0.width * scale ); sz1.height = cvRound( sz0.height * scale ); bool equalSizes = sz1.width == sz0.width && sz1.height == sz0.height; if( !equalSizes || cn != 1 ) { Mat sA, sB; if( cn != 1 ) { Mat gray; cvtColor(A, gray, COLOR_BGR2GRAY); resize(gray, sA, sz1, 0., 0., INTER_AREA); cvtColor(B, gray, COLOR_BGR2GRAY); resize(gray, sB, sz1, 0., 0., INTER_AREA); } else { resize(A, sA, sz1, 0., 0., INTER_AREA); resize(B, sB, sz1, 0., 0., INTER_AREA); } A = sA; B = sB; } int count_y = COUNT; int count_x = cvRound((double)COUNT*sz1.width/sz1.height); count = count_x * count_y; pA.resize(count); pB.resize(count); status.resize(count); for( i = 0, k = 0; i < count_y; i++ ) for( j = 0; j < count_x; j++, k++ ) { pA[k].x = (j+0.5f)*sz1.width/count_x; pA[k].y = (i+0.5f)*sz1.height/count_y; } // find the corresponding points in B calcOpticalFlowPyrLK(A, B, pA, pB, status, noArray(), Size(21, 21), 3, TermCriteria(TermCriteria::MAX_ITER,40,0.1)); // repack the remained points for( i = 0, k = 0; i < count; i++ ) if( status[i] ) { if( i > k ) { pA[k] = pA[i]; pB[k] = pB[i]; } k++; } count = k; pA.resize(count); pB.resize(count); } else CV_Error( Error::StsUnsupportedFormat, "Both input images must have either 8uC1 or 8uC3 type" ); good_idx.resize(count); if( count < ransacSize0 ) return Mat(); Rect brect = boundingRect(pB); std::vector<Point2f> a(ransacSize0); std::vector<Point2f> b(ransacSize0); // RANSAC stuff: // 1. find the consensus for( k = 0; k < ransacMaxIters; k++ ) { std::vector<int> idx(ransacSize0); // choose random 3 non-complanar points from A & B for( i = 0; i < ransacSize0; i++ ) { for( k1 = 0; k1 < ransacMaxIters; k1++ ) { idx[i] = rng.uniform(0, count); for( j = 0; j < i; j++ ) { if( idx[j] == idx[i] ) break; // check that the points are not very close one each other if( fabs(pA[idx[i]].x - pA[idx[j]].x) + fabs(pA[idx[i]].y - pA[idx[j]].y) < FLT_EPSILON ) break; if( fabs(pB[idx[i]].x - pB[idx[j]].x) + fabs(pB[idx[i]].y - pB[idx[j]].y) < FLT_EPSILON ) break; } if( j < i ) continue; if( i+1 == ransacSize0 ) { // additional check for non-complanar vectors a[0] = pA[idx[0]]; a[1] = pA[idx[1]]; a[2] = pA[idx[2]]; b[0] = pB[idx[0]]; b[1] = pB[idx[1]]; b[2] = pB[idx[2]]; double dax1 = a[1].x - a[0].x, day1 = a[1].y - a[0].y; double dax2 = a[2].x - a[0].x, day2 = a[2].y - a[0].y; double dbx1 = b[1].x - b[0].x, dby1 = b[1].y - b[0].y; double dbx2 = b[2].x - b[0].x, dby2 = b[2].y - b[0].y; const double eps = 0.01; if( fabs(dax1*day2 - day1*dax2) < eps*std::sqrt(dax1*dax1+day1*day1)*std::sqrt(dax2*dax2+day2*day2) || fabs(dbx1*dby2 - dby1*dbx2) < eps*std::sqrt(dbx1*dbx1+dby1*dby1)*std::sqrt(dbx2*dbx2+dby2*dby2) ) continue; } break; } if( k1 >= ransacMaxIters ) break; } if( i < ransacSize0 ) continue; // estimate the transformation using 3 points getRTMatrix( a, b, 3, M, fullAffine ); const double* m = M.ptr<double>(); for( i = 0, good_count = 0; i < count; i++ ) { if( std::abs( m[0]*pA[i].x + m[1]*pA[i].y + m[2] - pB[i].x ) + std::abs( m[3]*pA[i].x + m[4]*pA[i].y + m[5] - pB[i].y ) < std::max(brect.width,brect.height)*0.05 ) good_idx[good_count++] = i; } if( good_count >= count*ransacGoodRatio ) break; } if( k >= ransacMaxIters ) return Mat(); if( good_count < count ) { for( i = 0; i < good_count; i++ ) { j = good_idx[i]; pA[i] = pA[j]; pB[i] = pB[j]; } } getRTMatrix( pA, pB, good_count, M, fullAffine ); M.at<double>(0, 2) /= scale; M.at<double>(1, 2) /= scale; return M; }
Convert Matrix Multiplication from Python to C++
My first programming language is python and now im trying to convert the python code to C++ code. C++ code will be used later in QT Creator. My python code is : import numpy as np P0 = 10 P1 = 20 P2 = 30 P3 = 40 Koef = [[-1,3,-3,1],[2,-5,4,-1],[-1,0,1,0],[0,2,0,0]] mKoef = np.matrix(Koef) Px = [[P0],[P1],[P2],[P3]] mPx = np.matrix(Px) t = 0.01 sr = [t**3,t**2,t,1] msr = np.matrix(sr) C = 0.5 * msr * mKoef * mPx print(C) And the result which i get is 20.1. But if I try to do same operation in C++ i get '0x75cc60' with no errors. I don't even know what it means. My C++ code (UPDATED!) : Now i get correct result 20.1. But for some reason if i comment out MatrixP2 the code doesn't work. And there seems to be a problem with reading values from MatrixProduct for some reason. float t = 0.01; int P0 = 10; int P1 = 20; int P2 = 30; int P3 = 40; float t3 = pow(t,3); float t2 = pow(t,2); int MatrixKoef[4][4] = {{-1, 3, -3, 1}, {2, -5, 4, -1}, {-1, 0, 1, 0}, {0, 2, 0, 0}}; float MatrixSR[1][4] = {t3,t2,t,1}; int MatrixP[4][1] = {{P0},{P1},{P2},{P3}}; int MatrixP2[1][4] = {5,4,3,2}; float MatrixProduct[1][1] = {0}; float MatrixFinale[1] = {0}; for (int row = 0; row < 1; row++) { for (int col = 0; col < 4; col++) { for (int inner = 0; inner < 4; inner++) { MatrixProduct[row][col] += 0.5 * MatrixSR[row][inner] * MatrixKoef[inner][col]; } std::cout << MatrixProduct[row][col] << " "; } std::cout << "\n"; } for (int row = 0; row<1;row++){ for (int col = 0; col<4; col++){ MatrixFinale[0] += MatrixProduct[1][-1+col] * MatrixP[0][col]; std::cout << MatrixProduct[1][-1+col] << " "; std::cout << MatrixP[0][col] << " "; std::cout << col; std::cout << "\n"; } std::cout << MatrixFinale[0] << " "; } All help will be appreciated! Thank you.
I am not sure why you are looping, but it should be std::cout << MatrixFinale[row] << " "; Also, as everybody has already pointed out, '0x75cc60' is the memory address of you MatrixFinale variable.
After fixing matrix declaration. All problems were fixed. Correct C++ code : float t = 0.01; int P0 = 10; int P1 = 20; int P2 = 30; int P3 = 40; float t3 = pow(t,3); float t2 = pow(t,2); int MatrixKoef[4][4] = {{-1, 3, -3, 1}, {2, -5, 4, -1}, {-1, 0, 1, 0}, {0, 2, 0, 0}}; float MatrixSR[] = {t3,t2,t,1}; int MatrixP[] = {P0,P1,P2,P3}; float MatrixProduct[] = {0,0,0,0}; float MatrixFinal[] = {0}; for (int row = 0; row < 1; row++) { for (int col = 0; col < 4; col++) { for (int inner = 0; inner < 4; inner++) { MatrixProduct[col] += 0.5 * (MatrixSR[inner] * MatrixKoef[inner][col]); } } for (int inner = 0; inner < 4; inner++) { MatrixFinal[0] += MatrixProduct[inner] * MatrixP[inner]; } std::cout << MatrixFinal[0] << " "; }
Flatten a Two Dimensional array going in a clockwise direction [duplicate]
How do I print a 5×5 two-dimensional array in spiral order? Is there any formula so that I can print an array of any size in spiral order?
The idea is to treat the matrix as a series of layers, top-right layers and bottom-left layers. To print the matrix spirally we can peel layers from these matrix, print the peeled part and recursively call the print on the left over part. The recursion terminates when we don't have any more layers to print. Input matrix: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 1 After peeling top-right layer: 1 2 3 4 8 5 6 7 2 9 0 1 6 3 4 5 1 7 8 9 After peeling bottom-left layer from sub-matrix: 6 7 5 0 1 9 4 5 3 7 8 9 After peeling top-right layer from sub-matrix: 6 7 1 0 5 4 After peeling bottom-left layer from sub-matrix: 0 4 Recursion terminates. C functions: // function to print the top-right peel of the matrix and // recursively call the print bottom-left on the submatrix. void printTopRight(int a[][COL], int x1, int y1, int x2, int y2) { int i = 0, j = 0; // print values in the row. for(i = x1; i<=x2; i++) { printf("%d ", a[y1][i]); } // print values in the column. for(j = y1 + 1; j <= y2; j++) { printf("%d ", a[j][x2]); } // see if more layers need to be printed. if(x2-x1 > 0) { // if yes recursively call the function to // print the bottom left of the sub matrix. printBottomLeft(a, x1, y1 + 1, x2-1, y2); } } // function to print the bottom-left peel of the matrix and // recursively call the print top-right on the submatrix. void printBottomLeft(int a[][COL], int x1, int y1, int x2, int y2) { int i = 0, j = 0; // print the values in the row in reverse order. for(i = x2; i>=x1; i--) { printf("%d ", a[y2][i]); } // print the values in the col in reverse order. for(j = y2 - 1; j >= y1; j--) { printf("%d ", a[j][x1]); } // see if more layers need to be printed. if(x2-x1 > 0) { // if yes recursively call the function to // print the top right of the sub matrix. printTopRight(a, x1+1, y1, x2, y2-1); } } void printSpiral(int arr[][COL]) { printTopRight(arr,0,0,COL-1,ROW-1); printf("\n"); }
Pop top row Transpose and flip upside-down (same as rotate 90 degrees counter-clockwise) Go to 1 Python 2 code: import itertools arr = [[1,2,3,4], [12,13,14,5], [11,16,15,6], [10,9,8,7]] def transpose_and_yield_top(arr): while arr: yield arr[0] arr = list(reversed(zip(*arr[1:]))) print list(itertools.chain(*transpose_and_yield_top(arr))) For python 3x: import itertools arr = [[1,2,3,4], [12,13,14,5], [11,16,15,6], [10,9,8,7]] def transpose_and_yield_top(arr): while arr: yield arr[0] arr = list(reversed(list(zip(*arr[1:])))) print(list(itertools.chain(*transpose_and_yield_top(arr))))
I see that no one has use only one for loop and without recursion in the code, and so I want to contribute. The idea is like this: Imagine there is a turtle standing at point (0,0), that is, top-left corner, facing east (to the right) It will keep going forward and each time it sees a sign, the turtle will turn right So if we put the turtle at point (0,0) facing right-ward, and if we place the signs at appropriate places, the turtle will traverse the array in spiral way. Now the problem is: "Where to put the signs?" Let's see where we should put the signs (marked by #, and numbers by O): For a grid that looks like this: O O O O O O O O O O O O O O O O We put the signs like this: O O O # # O # O O # # O # O O # For a grid that looks like this: O O O O O O O O O O O O We put the signs like this: O O # # # O O # O # O # And for a grid that looks like this: O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O We put the signs like this: O O O O O O # # O O O O # O O # O O # O O O # O O O # O # O O O O O # We can see that, unless the point is at the top-left part, the signs are places at points where the distances to the closest horizontal border and the closest vertical border are the same, while for the top-left part, the distance to the top border is one more than the distance to the left border, with priority given to top-right in case the point is horizontally centered, and to top-left in case the point is vertically centered. This can be realized in a simple function quite easily, by taking the minimum of (curRow and height-1-curRow), then the minimum of (curCol and width-1-curCol) and compare if they are the same. But we need to account for the upper-left case, that is, when the minimum is curRow and curCol themselves. In that case we reduce the vertical distance accordingly. Here is the C code: #include <stdio.h> int shouldTurn(int row, int col, int height, int width){ int same = 1; if(row > height-1-row) row = height-1-row, same = 0; // Give precedence to top-left over bottom-left if(col >= width-1-col) col = width-1-col, same = 0; // Give precedence to top-right over top-left row -= same; // When the row and col doesn't change, this will reduce row by 1 if(row==col) return 1; return 0; } int directions[4][2] = {{0,1},{1,0},{0,-1},{-1,0}}; void printSpiral(int arr[4][4], int height, int width){ int directionIdx=0, i=0; int curRow=0, curCol=0; for(i=0; i<height*width; i++){ printf("%d ",arr[curRow][curCol]); if(shouldTurn(curRow, curCol, height, width)){ directionIdx = (directionIdx+1)%4; } curRow += directions[directionIdx][0]; curCol += directions[directionIdx][1]; } printf("\n"); } int main(){ int arr[4][4]= {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}; printSpiral(arr, 4, 4); printSpiral(arr, 3, 4); } Which outputs: 1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 1 2 3 4 8 12 11 10 9 5 6 7
Here are the three interesting ways Reading in spiral way can be treated like a snake moving towards boundary and turning on hitting the boundary or itself (I find it elegant and most efficient being a single loop of N iterations) ar = [ [ 0, 1, 2, 3, 4], [15, 16, 17, 18, 5], [14, 23, 24, 19, 6], [13, 22, 21, 20, 7], [12, 11, 10, 9, 8]] def print_spiral(ar): """ assuming a rect array """ rows, cols = len(ar), len(ar[0]) r, c = 0, -1 # start here nextturn = stepsx = cols # move so many steps stepsy = rows-1 inc_c, inc_r = 1, 0 # at each step move this much turns = 0 # how many times our snake had turned for i in range(rows*cols): c += inc_c r += inc_r print ar[r][c], if i == nextturn-1: turns += 1 # at each turn reduce how many steps we go next if turns%2==0: nextturn += stepsx stepsy -= 1 else: nextturn += stepsy stepsx -= 1 # change directions inc_c, inc_r = -inc_r, inc_c print_spiral(ar) output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 A recursive approach would be to print outer layer and call same function for inner rectangle e.g. def print_spiral(ar, sr=0, sc=0, er=None, ec=None): er = er or len(ar)-1 ec = ec or len(ar[0])-1 if sr > er or sc > ec: print return # print the outer layer top, bottom, left, right = [], [], [], [] for c in range(sc,ec+1): top.append(ar[sr][c]) if sr != er: bottom.append(ar[er][ec-(c-sc)]) for r in range(sr+1,er): right.append(ar[r][ec]) if ec != sc: left.append(ar[er-(r-sr)][sc]) print " ".join([str(a) for a in top + right + bottom + left]), # peel next layer of onion print_spiral(ar, sr+1, sc+1, er-1, ec-1) Finally here is a small snippet to do it, not efficient but fun :), basically it prints top row, and rotates whole rectangle anti-clockwise and repeats def print_spiral(ar): if not ar: return print " ".join(str(a) for a in ar[0]), ar = zip(*[ reversed(row) for row in ar[1:]]) print_spiral(ar)
This program works for any n*n matrix.. public class circ { public void get_circ_arr (int n,int [][] a) { int z=n; { for (int i=0;i<n;i++) { for (int l=z-1-i;l>=i;l--) { int k=i; System.out.printf("%d",a[k][l]); } for (int j=i+1;j<=z-1-i;j++) { int k=i; { System.out.printf("%d",a[j][k]); } } for (int j=i+1;j<=z-i-1;j++) { int k=z-1-i; { System.out.printf("%d",a[k][j]); } } for (int j=z-2-i;j>=i+1;j--) { int k=z-i-1; { System.out.printf("%d",a[j][k]); } } } } } } Hope it helps
I was obsessed with this problem when I was learning Ruby. This was the best I could do: def spiral(matrix) matrix.empty? ? [] : matrix.shift + spiral(matrix.transpose.reverse) end You can check out some of my other solutions by stepping back through the revisions in this gist. Also, if you follow the link back to whom I forked the gist from, you'll find some other clever solutions. Really interesting problem that can be solved in multiple elegant ways — especially in Ruby.
JavaScript solution: var printSpiral = function (matrix) { var i; var top = 0; var left = 0; var bottom = matrix.length; var right = matrix[0].length; while (top < bottom && left < right) { //print top for (i = left; i < right; i += 1) { console.log(matrix[top][i]); } top++; //print right column for (i = top; i < bottom; i += 1) { console.log(matrix[i][right - 1]); } right--; if (top < bottom) { //print bottom for (i = right - 1; i >= left; i -= 1) { console.log(matrix[bottom - 1][i]); } bottom--; } if (left < right) { //print left column for (i = bottom - 1; i >= top; i -= 1) { console.log(matrix[i][left]); } left++; } } };
One solution involves directions right, left, up, down, and their corresponding limits (indices). Once the first row is printed, and direction changes (from right) to down, the row is discarded by incrementing the upper limit. Once the last column is printed, and direction changes to left, the column is discarded by decrementing the right hand limit... Details can be seen in the self-explanatory C code. #include <stdio.h> #define N_ROWS 5 #define N_COLS 3 void print_spiral(int a[N_ROWS][N_COLS]) { enum {up, down, left, right} direction = right; int up_limit = 0, down_limit = N_ROWS - 1, left_limit = 0, right_limit = N_COLS - 1, downcount = N_ROWS * N_COLS, row = 0, col = 0; while(printf("%d ", a[row][col]) && --downcount) if(direction == right) { if(++col > right_limit) { --col; direction = down; ++up_limit; ++row; } } else if(direction == down) { if(++row > down_limit) { --row; direction = left; --right_limit; --col; } } else if(direction == left) { if(--col < left_limit) { ++col; direction = up; --down_limit; --row; } } else /* direction == up */ if(--row < up_limit) { ++row; direction = right; ++left_limit; ++col; } } void main() { int a[N_ROWS][N_COLS] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; print_spiral(a); } Link for Testing and Download.
Given a matrix of chars, implement a method that prints all characters in the following order: first the outer circle, then the next one and so on. public static void printMatrixInSpiral(int[][] mat){ if(mat.length == 0|| mat[0].length == 0){ /* empty matrix */ return; } StringBuffer str = new StringBuffer(); int counter = mat.length * mat[0].length; int startRow = 0; int endRow = mat.length-1; int startCol = 0; int endCol = mat[0].length-1; boolean moveCol = true; boolean leftToRight = true; boolean upDown = true; while(counter>0){ if(moveCol){ if(leftToRight){ /* printing entire row left to right */ for(int i = startCol; i <= endCol ; i++){ str.append(mat[startRow][i]); counter--; } leftToRight = false; moveCol = false; startRow++; } else{ /* printing entire row right to left */ for(int i = endCol ; i >= startCol ; i--){ str.append(mat[endRow][i]); counter--; } leftToRight = true; moveCol = false; endRow--; } } else { if(upDown){ /* printing column up down */ for(int i = startRow ; i <= endRow ; i++){ str.append(mat[i][endCol]); counter--; } upDown = false; moveCol = true; endCol--; } else { /* printing entire col down up */ for(int i = endRow ; i >= startRow ; i--){ str.append(mat[i][startCol]); counter--; } upDown = true; moveCol = true; startCol++; } } } System.out.println(str.toString()); }
Two dimensional N*N Matrix is Square matrix Idea: We have to traverse in four different directions to traverse like spiral. We have to traverse inside matrix once one layer of spiral is over. So total, we need 5 loops, 4 loops to traverse like spiral and 1 loop to traverse through the layers. public void printSpiralForm(int[][] a, int length) { for( int i = 0 , j = length-1 ; i < j ; i++ , j-- ) { for( int k = i ; k < j ; k++ ) { System.out.print( a[i][k] + " " ) ; } for( int k = i ; k < j ; k++ ) { System.out.print(a[k][j] + " "); } for( int k = j ; k > i ; k-- ) { System.out.print(a[j][k] + " ") ; } for( int k = j ; k > i ; k-- ) { System.out.print( a[k][i] + " " ) ; } } if ( length % 2 == 1 ) { System.out.println( a[ length/2 ][ length/2 ] ) ; } }
Just keep it simple --> public class spiralMatrix { public static void printMatrix(int[][] matrix, int rows, int col) { int rowStart=0; int rowEnd=rows-1; int colStart=0; int colEnd=col-1; while(colStart<=colEnd && rowStart<=rowEnd) { for(int i=colStart;i<colEnd;i++) System.out.println(matrix[rowStart][i]); for(int i=rowStart;i<rowEnd;i++) System.out.println(matrix[i][colEnd]); for(int i=colEnd;i>colStart;i--) System.out.println(matrix[rowEnd][i]); for(int i=rowEnd;i>rowStart;i--) System.out.println(matrix[i][colStart]); rowStart++; colEnd--; rowEnd--; colStart++; } } public static void main(String[] args){ int[][] array={{1,2,3,4},{5,6,7,8}}; printMatrix(array,2,4); } }
This is my implementation: public static void printMatrix(int matrix[][], int M, int N){ int level = 0; int min = (M < N) ? M:N; System.out.println(); while(level <= min/2){ for(int j = level; j < N - level - 1; j++){ System.out.print(matrix[level][j] + "\t"); } for(int i = level; i < M - level - 1; i++) { System.out.print(matrix[i][N - level - 1] + "\t"); } for(int j = N - level - 1; j > level; j--){ System.out.print(matrix[M - level - 1][j] + "\t"); } for(int i = M - level - 1; i > level; i-- ){ System.out.print(matrix[i][level] + "\t"); } level++; } }
Here is my solution. Please correct if I'm wrong. class Spiral: def spiralOrder(self, A): result = [] c = [] c.append(A[0]) b = A[1:] while len(b) > 0: b = self.rotate(b) c.append(b[0]) b = b[1:] for item in c: for fitem in item: print fitem, result.append(fitem) return result def rotate(self,a): b = [] l = zip(*a) for i in xrange(len(l)-1,-1,-1): b.append(list(l[i])) return b if __name__ == '__main__': a = [[1, 2, 3,3], [4, 5, 6,6], [7, 8, 9,10]] s = Spiral() s.spiralOrder(a)
Slash Top Row -> Transpose -> Flip -> Repeat. void slashTransposeFlip(int[][] m){ if( m.length * m[0].length == 1){ //only one element left System.out.print(m[0][0]); }else{ //print the top row for(int a:m[0]){System.out.print(a+" ");} //slash the top row from the matrix. int[][] n = Arrays.copyOfRange(m,1,m.length); int[][] temp = n; int rows = temp.length; int columns = temp[0].length; //invert rows and columns and create new array n = new int[columns][rows]; //transpose for(int x=0;x<rows;x++) for(int y=0;y<columns;y++) n[y][x] = temp[x][y]; //flipping time for (int i = 0; i < n.length / 2; i++) { int[] t = n[i]; n[i] = n[n.length - 1 - i]; n[n.length - 1 - i] = t; } //recursively call again the reduced matrix. slashTransposeFlip(n); } }
Complexity: Single traverse O(n) Please let me add my single loop answer with complexity O(n). I have observed that during left-right and right-left traverse of the matrix, there is an increase and decrease by one respectively in the row-major index. Similarly, for the top-bottom and bottom-top traverse there is increase and decrease by n_cols. Thus I made an algorithm for that. For example, given a (3x5) matrix with entries the row-major indexes the print output is: 1,2,3,4,5,10,15,14,13,12,11,6,7,8,9. ------->(+1) ^ 1 2 3 4 5 | (+n_cols) | 6 7 8 9 10 | (-n_cols) | 11 12 13 14 15 (-1)<------- Code solution: #include <iostream> using namespace std; int main() { // your code goes here bool leftToRight=true, topToBottom=false, rightToLeft=false, bottomToTop=false; int idx=0; int n_rows = 3; int n_cols = 5; int cnt_h = n_cols, cnt_v = n_rows, cnt=0; int iter=1; for (int i=0; i <= n_rows*n_cols + (n_rows - 1)*(n_cols - 1)/2; i++){ iter++; if(leftToRight){ if(cnt >= cnt_h){ cnt_h--; cnt=0; leftToRight = false; topToBottom = true; //cout << "Iter: "<< iter << " break_leftToRight"<<endl; }else{ cnt++; idx++; //cout << "Iter: "<< iter <<" idx: " << idx << " cnt: "<< cnt << " cnt_h: "<< cnt_h<< endl; cout<< idx << endl; } }else if(topToBottom){ if(cnt >= cnt_v-1){ cnt_v--; cnt=0; leftToRight = false; topToBottom = false; rightToLeft=true; //cout << "Iter: "<< iter << " break_topToBottom"<<endl; }else{ cnt++; idx+=n_cols; //cout << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_v: "<< cnt_h<< endl; cout << idx <<endl; } }else if(rightToLeft){ if(cnt >= cnt_h){ cnt_h--; cnt=0; leftToRight = false; topToBottom = false; rightToLeft=false; bottomToTop=true; //cout << "Iter: "<< iter << " break_rightToLeft"<<endl; //cout<< idx << endl; }else{ cnt++; idx--; //cout << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_h: "<< cnt_h<< endl; cout << idx <<endl; } }else if(bottomToTop){ if(cnt >= cnt_v-1){ cnt_v--; cnt=0; leftToRight = true; topToBottom = false; rightToLeft=false; bottomToTop=false; //cout << "Iter: "<< iter << " break_bottomToTop"<<endl; }else{ cnt++; idx-=n_cols; //cout << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_v: "<< cnt_h<< endl; cout<< idx << endl; } } //cout << i << endl; } return 0; }
function spiral(a) { var s = []; while (a.length) { // concat 1st row, push last cols, rotate 180 (reverse inner/outer)... s = s.concat(a.shift()); a = a .map(function(v) { s.push(v.pop()); return v.reverse(); }) .reverse(); } return s; } var arr = [ [1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7] ]; console.log(spiral(arr));// -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] arr = [ [0, 1, 2, 3, 4], [15, 16, 17, 18, 5], [14, 23, 24, 19, 6], [13, 22, 21, 20, 7], [12, 11, 10, 9, 8] ]; console.log(spiral(arr));// -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
For printing a 2-D matrix consider matrix as a composition of rectangles and/or line where smaller rectangle is fitted into larger one, take boundary of matrix which forms a rectangle to be printed, starting with up-left element each time in each layer; once done with this go inside for next layer of smaller rectangle, in case i don't have a rectangle then it should be line to be printed, a horizontal or vertical. I have pasted the code with an example matrix, HTH. #include <stdio.h> int a[2][4] = { 1, 2 ,3, 44, 8, 9 ,4, 55 }; void print(int, int, int, int); int main() { int row1, col1, row2, col2; row1=0; col1=0; row2=1; col2=3; while(row2>=row1 && col2>=col1) { print(row1, col1, row2, col2); row1++; col1++; row2--; col2--; } return 0; } void print(int row1, int col1, int row2, int col2) { int i=row1; int j=col1; /* This is when single horizontal line needs to be printed */ if( row1==row2 && col1!=col2) { for(j=col1; j<=col2; j++) printf("%d ", a[i][j]); return; } /* This is when single vertical line needs to be printed */ if( col1==col2 && row1!=row2) { for(i=row1; j<=row2; i++) printf("%d ", a[i][j]); return; } /* This is reached when there is a rectangle to be printed */ for(j=col1; j<=col2; j++) printf("%d ", a[i][j]); for(j=col2,i=row1+1; i<=row2; i++) printf("%d ", a[i][j]); for(i=row2,j=col2-1; j>=col1; j--) printf("%d ", a[i][j]); for(j=col1,i=row2-1; i>row1; i--) printf("%d ", a[i][j]); }
Here is my implementation in Java: public class SpiralPrint { static void spiral(int a[][],int x,int y){ //If the x and y co-ordinate collide, break off from the function if(x==y) return; int i; //Top-left to top-right for(i=x;i<y;i++) System.out.println(a[x][i]); //Top-right to bottom-right for(i=x+1;i<y;i++) System.out.println(a[i][y-1]); //Bottom-right to bottom-left for(i=y-2;i>=x;i--) System.out.println(a[y-1][i]); //Bottom left to top-left for(i=y-2;i>x;i--) System.out.println(a[i][x]); //Recursively call spiral spiral(a,x+1,y-1); } public static void main(String[] args) { int a[][]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}; spiral(a,0,4); /*Might be implemented without the 0 on an afterthought, all arrays will start at 0 anyways. The second parameter will be the dimension of the array*/ } }
//shivi..coding is adictive!! #include<shiviheaders.h> #define R 3 #define C 6 using namespace std; void PrintSpiral(int er,int ec,int arr[R][C]) { int sr=0,sc=0,i=0; while(sr<=er && sc<=ec) { for(int i=sc;i<=ec;++i) cout<<arr[sr][i]<<" "; ++sr; for(int i=sr;i<=er;++i) cout<<arr[i][ec]<<" "; ec--; if(sr<=er) { for(int i=ec;i>=sc;--i) cout<<arr[er][i]<<" "; er--; } if(sc<=ec) { for(int i=er;i>=sr;--i) cout<<arr[i][sc]<<" "; ++sc; } } } int main() { int a[R][C] = { {1, 2, 3, 4, 5, 6}, {7, 8, 9, 10, 11, 12}, {13, 14, 15, 16, 17, 18} }; PrintSpiral(R-1, C-1, a); }
int N = Integer.parseInt(args[0]); // create N-by-N array of integers 1 through N int[][] a = new int[N][N]; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) a[i][j] = 1 + N*i + j; // spiral for (int i = N-1, j = 0; i > 0; i--, j++) { for (int k = j; k < i; k++) System.out.println(a[j][k]); for (int k = j; k < i; k++) System.out.println(a[k][i]); for (int k = i; k > j; k--) System.out.println(a[i][k]); for (int k = i; k > j; k--) System.out.println(a[k][j]); } // special case for middle element if N is odd if (N % 2 == 1) System.out.println(a[(N-1)/2][(N-1)/2]); } }
Java code if anybody is interested. Input: 4 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 Output: 1 2 3 4 8 3 7 6 5 4 9 5 6 7 2 1 public class ArraySpiralPrinter { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); //marrix size //read array int[][] ar = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { ar[i][j] = sc.nextInt(); } } printTopRight(0, 0, n - 1, n - 1, ar); } //prints top and right layers. //(x1,y1) to (x1, y2) - top layer & (x1,y2) to (x2, y2) private static void printTopRight(int x1, int y1, int x2, int y2, int[][] ar) { //print row values - top for (int y = y1; y <= y2; y++) { System.out.printf("%d ", ar[x1][y]); } //print column value - right for (int x = x1 + 1; x <= x2; x++) { System.out.printf("%d ", ar[x][y2]); } //are there any remaining layers if (x2 - x1 > 0) { //call printBottemLeft printBottomLeft(x1 + 1, y1, x2, y2 - 1, ar); } } //prints bottom and left layers in reverse order //(x2,y2) to (x2, y1) - bottom layer & (x2,y1) to (x1, y1) private static void printBottomLeft(int x1, int y1, int x2, int y2, int[][] ar) { //print row values in reverse order - bottom for (int y = y2; y >= y1; y--) { System.out.printf("%d ", ar[x2][y]); } //print column value in reverse order - left for (int x = x2-1; x >= x1; x--) { System.out.printf("%d ", ar[x][y1]); } //are there any remaining layers if (x2 - x1 > 0) { printTopRight(x1, y1 + 1, x2 - 1, y2, ar); } } }
This is a recursive version in C that I could think of:- void printspiral (int[][100],int, int, int, int); int main() { int r,c, i, j; printf ("Enter the dimensions of the matrix"); scanf("%d %d", &r, &c); int arr[r][100]; int min = (r<c?r:c); if (min%2 != 0) min = min/2 +1; for (i = 0;i<r; i++) for (j = 0; j<c; j++) scanf ("%d",&arr[i][j]); printspiral(arr,0,r,c,min ); } void printspiral (int arr[][100], int i, int j, int k, int min) { int a; for (a = i; a<k;a++) printf("%d\n", arr[i][a]); for (a=i+1;a<j;a++) printf ("%d\n", arr[a][k-1]); for (a=k-2; a>i-1;a--) printf("%d\n", arr[j-1][a]); for (a=j-2; a>i; a--) printf("%d\n", arr[a][i]); if (i < min) printspiral(arr,i+1, j-1,k-1, min); }
http://www.technicalinterviewquestions.net/2009/03/print-2d-array-matrix-spiral-order.html here is the best explanation for the above answer :) along with diagram :)
public static void printSpiral1(int array[][],int row,int col){ int rowStart=0,colStart=0,rowEnd=row-1,colEnd=col-1; int i; while(rowStart<=rowEnd && colStart<= colEnd){ for(i=colStart;i<=colEnd;i++) System.out.print(" "+array[rowStart][i]); for(i=rowStart+1;i<=rowEnd;i++) System.out.print(" "+array[i][colEnd]); for(i=colEnd-1;i>=colStart;i--) System.out.print(" "+array[rowEnd][i]); for(i=rowEnd-1;i>=rowStart+1;i--) System.out.print(" "+array[i][colStart]); rowStart++; colStart++; rowEnd--; colEnd--; } }
public class SpiralPrint{ //print the elements of matrix in the spiral order. //my idea is to use recursive, for each outer loop public static void printSpiral(int[][] mat, int layer){ int up = layer; int buttom = mat.length - layer - 1; int left = layer; int right = mat[0].length - layer - 1; if(up > buttom+1 || left > right + 1) return; // termination condition //traverse the other frame, //print up for(int i = left; i <= right; i ++){ System.out.print( mat[up][i]+ " " ); } //print right for(int i = up + 1; i <=buttom; i ++){ System.out.print(mat[i][right] + " "); } //print buttom for(int i = right - 1; i >= left; i --){ System.out.print(mat[buttom][i] + " "); } //print left for(int i = buttom - 1; i > up; i --){ System.out.print(mat[i][left] + " "); } //recursive call for the next level printSpiral(mat, layer + 1); } public static void main(String[] args){ int[][] mat = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}}; int[][] mat2 = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}}; SpiralPrint.printSpiral(mat2,0); return; } }
Here is my solution in C#: public static void PrintSpiral(int[][] matrix, int n) { if (matrix == null) { return; } for (int layer = 0; layer < Math.Ceiling(n / 2.0); layer++) { var start = layer; var end = n - layer - 1; var offset = end - 1; Console.Write("Layer " + layer + ": "); // Center case if (start == end) { Console.Write(matrix[start][start]); } // Top for (int i = start; i <= offset; i++) { Console.Write(matrix[start][i] + " "); } // Right for (int i = start; i <= offset; i++) { Console.Write(matrix[i][end] + " "); } // Bottom for (int i = end; i > start; i--) { Console.Write(matrix[end][i] + " "); } // Left for (int i = end; i > start; i--) { Console.Write(matrix[i][start] + " "); } Console.WriteLine(); } }
Here's my approach using an Iterator . Note this solves almost the same problem.. Complete code here : https://github.com/rdsr/algorithms/blob/master/src/jvm/misc/FillMatrix.java import java.util.Iterator; class Pair { final int i; final int j; Pair(int i, int j) { this.i = i; this.j = j; } #Override public String toString() { return "Pair [i=" + i + ", j=" + j + "]"; } } enum Direction { N, E, S, W; } class SpiralIterator implements Iterator<Pair> { private final int r, c; int ri, ci; int cnt; Direction d; // current direction int level; // spiral level; public SpiralIterator(int r, int c) { this.r = r; this.c = c; d = Direction.E; level = 1; } #Override public boolean hasNext() { return cnt < r * c; } #Override public Pair next() { final Pair p = new Pair(ri, ci); switch (d) { case E: if (ci == c - level) { ri += 1; d = changeDirection(d); } else { ci += 1; } break; case S: if (ri == r - level) { ci -= 1; d = changeDirection(d); } else { ri += 1; } break; case W: if (ci == level - 1) { ri -= 1; d = changeDirection(d); } else { ci -= 1; } break; case N: if (ri == level) { ci += 1; level += 1; d = changeDirection(d); } else { ri -= 1; } break; } cnt += 1; return p; } private static Direction changeDirection(Direction d) { switch (d) { case E: return Direction.S; case S: return Direction.W; case W: return Direction.N; case N: return Direction.E; default: throw new IllegalStateException(); } } #Override public void remove() { throw new UnsupportedOperationException(); } } public class FillMatrix { static int[][] fill(int r, int c) { final int[][] m = new int[r][c]; int i = 1; final Iterator<Pair> iter = new SpiralIterator(r, c); while (iter.hasNext()) { final Pair p = iter.next(); m[p.i][p.j] = i; i += 1; } return m; } public static void main(String[] args) { final int r = 19, c = 19; final int[][] m = FillMatrix.fill(r, c); for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { System.out.print(m[i][j] + " "); } System.out.println(); } } }
Complete pure C program for any 2D array matrix with given row x column. #include <stdio.h> void printspiral(int *p,int r, int c) { int i=0,j=0,m=1,n=0; static int firstrun=1,gCol; if (!p||r<=0||c<=0) return ; if(firstrun) { gCol=c; firstrun=0; } for(i=0,j=0;(0<=i && i<c)&&(0<=j && j<r);i+=m,j+=n) { printf(" %d",p[i+j*gCol]); if (i==0 && j==1 && (i+1)!=c) break; else if (i+1==c && !j) {m=0;n=1;} else if (i+1==c && j+1==r && j) {n=0;m=-1;} else if (i==0 && j+1==r && j) {m=0;n=-1;} } printspiral(&p[i+j*gCol+1],r-2,c-2); firstrun=1; printf("\n"); } int main() { int a[3][3]={{0,1,2},{3,4,5},{6,7,8}}; int b[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}; int c[4][3]={{0,1,2},{3,4,5},{6,7,8},{9,10,11}}; int d[3][1]={{0},{1},{2}}; int e[1][3]={{0,1,2}}; int f[1][1]={{0}}; int g[5][5]={{0,1,2,3,4},{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24}}; printspiral(a,3,3); printspiral(b,3,4); printspiral(c,4,3); printspiral(d,3,1); printspiral(e,1,3); printspiral(f,1,1); printspiral(g,5,5); return 0; }
This question is related to this one: Matrix arrangement issues in php The answers presented seem to work but are complicated to understand. A very simple way to solve this is divide and conquer i.e., after reading the edge, remove it and the next read will be much simpler. Check out a complete solution in PHP below: #The source number matrix $source[0] = array(1, 2, 3, 4); $source[1] = array(5, 6, 7, 8); $source[2] = array(9, 10, 11, 12); $source[3] = array(13, 14, 15, 16); $source[4] = array(17, 18, 19, 20); #Get the spiralled numbers $final_spiral_list = get_spiral_form($source); print_r($final_spiral_list); function get_spiral_form($matrix) { #Array to hold the final number list $spiralList = array(); $result = $matrix; while(count($result) > 0) { $resultsFromRead = get_next_number_circle($result, $spiralList); $result = $resultsFromRead['new_source']; $spiralList = $resultsFromRead['read_list']; } return $spiralList; } function get_next_number_circle($matrix, $read) { $unreadMatrix = $matrix; $rowNumber = count($matrix); $colNumber = count($matrix[0]); #Check if the array has one row or column if($rowNumber == 1) $read = array_merge($read, $matrix[0]); if($colNumber == 1) for($i=0; $i<$rowNumber; $i++) array_push($read, $matrix[$i][0]); #Check if array has 2 rows or columns if($rowNumber == 2 || ($rowNumber == 2 && $colNumber == 2)) { $read = array_merge($read, $matrix[0], array_reverse($matrix[1])); } if($colNumber == 2 && $rowNumber != 2) { #First read left to right for the first row $read = array_merge($read, $matrix[0]); #Then read down on right column for($i=1; $i<$rowNumber; $i++) array_push($read, $matrix[$i][1]); #..and up on left column for($i=($rowNumber-1); $i>0; $i--) array_push($read, $matrix[$i][0]); } #If more than 2 rows or columns, pick up all the edge values by spiraling around the matrix if($rowNumber > 2 && $colNumber > 2) { #Move left to right for($i=0; $i<$colNumber; $i++) array_push($read, $matrix[0][$i]); #Move top to bottom for($i=1; $i<$rowNumber; $i++) array_push($read, $matrix[$i][$colNumber-1]); #Move right to left for($i=($colNumber-2); $i>-1; $i--) array_push($read, $matrix[$rowNumber-1][$i]); #Move bottom to top for($i=($rowNumber-2); $i>0; $i--) array_push($read, $matrix[$i][0]); } #Now remove these edge read values to create a new reduced matrix for the next read $unreadMatrix = remove_top_row($unreadMatrix); $unreadMatrix = remove_right_column($unreadMatrix); $unreadMatrix = remove_bottom_row($unreadMatrix); $unreadMatrix = remove_left_column($unreadMatrix); return array('new_source'=>$unreadMatrix, 'read_list'=>$read); } function remove_top_row($matrix) { $removedRow = array_shift($matrix); return $matrix; } function remove_right_column($matrix) { $neededCols = count($matrix[0]) - 1; $finalMatrix = array(); for($i=0; $i<count($matrix); $i++) $finalMatrix[$i] = array_slice($matrix[$i], 0, $neededCols); return $finalMatrix; } function remove_bottom_row($matrix) { unset($matrix[count($matrix)-1]); return $matrix; } function remove_left_column($matrix) { $neededCols = count($matrix[0]) - 1; $finalMatrix = array(); for($i=0; $i<count($matrix); $i++) $finalMatrix[$i] = array_slice($matrix[$i], 1, $neededCols); return $finalMatrix; }
// Program to print a matrix in spiral order #include <stdio.h> int main(void) { // your code goes here int m,n,i,j,k=1,c1,c2,r1,r2;; scanf("%d %d",&m,&n); int a[m][n]; for(i=0;i<m;i++) { for(j=0;j<n;j++) { scanf("%d",&a[i][j]); } } r1=0; r2=m-1; c1=0; c2=n-1; while(k<=m*n) { for(i=c1;i<=c2;i++) { k++; printf("%d ",a[r1][i]); } for(j=r1+1;j<=r2;j++) { k++; printf("%d ",a[j][c2]); } for(i=c2-1;i>=c1;i--) { k++; printf("%d ",a[r2][i]); } for(j=r2-1;j>=r1+1;j--) { k++; printf("%d ",a[j][c1]); } c1++; c2--; r1++; r2--; } return 0; }
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.
Interpret data from Modbus ASCII in C
I have a reply from a MODBUS ASCII protocol device. I store the "data" part of the reply into an array in C: char test_reply[10]; char buffer[255]; //contains all the reply from modbus device following ascii protocol //store the "data part" of the reply to test_reply to fix endianness test_reply[0] = buffer[9]; test_reply[1] = buffer[10]; test_reply[2] = buffer[7]; test_reply[3] = buffer[8]; test_reply[4] = buffer[13]; test_reply[5] = buffer[14]; test_reply[6] = buffer[11]; test_reply[7] = buffer[12]; I print this one and I got: printf("this is the data reply: %s\n", test_reply) "this is the data reply: 7B346543" If I get the length of the string, I'm getting 8 (which I think is correct). I believe each of those characters can be interpreted like this: char(0x37) = 7 char(0x42) = B char(0x33) = 3 and so on... Now, I have to get a value of "229.20" from the reply. What I do is manually input them to a variable and compute using a command in python. like this: >> x = chr(0x7B) + chr(0x34) + chr(0x65) +chr(0x43) >> y = "".join(x) >> z = struct.unpack("<f",y) >> print z (229.2050,) I believe the way you do it in C is like on my previous post: Unpacking in C I want to ask if there is a way to do the other one in C
So what you need is a way to convert the 2 bytes sequence "7B" of { 0x37, 0x42 } to the single byte 0x7b. sscanf with a x format is what you need. Assuming you know you have only 8 useful characters in test_reply, that you have already dealt with endianness on your platform and want to store them in a 32 bits float, you can do: int i; float z; unsigned char *ix = (unsigned char *) &z; // you can always convert any address to a char * for(i=0; i<4; i++) { sscanf(test_reply + 2 * i, "%2hhx", &ix[i]); // 2 to process only 2 chars, hh to store only one byte } // control: printf("%f\n", z); // should output 229.205002
You are receiving from ModBus ASCII value of the HEX representation of float 229,20. You must convert they manually like in the following example. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <stdint.h> uint8_t getDigit ( uint8_t digit) { uint8_t retVal = 0; if ((digit >= '0') && (digit <= '9')) { retVal = digit - '0'; } else if ((digit >= 'A') && (digit <= 'F')) { retVal = digit - 'A' + 10; } else if ((digit >= 'a') && (digit <= 'f')) { retVal = digit - 'a' + 10; } else { printf("Wrong char\n"); } return retVal; } uint8_t ascii2bin (uint8_t hi, uint8_t lo) { uint8_t retVal = (getDigit(hi) << 4) | getDigit(lo); return retVal; } int main() { char *ModBus_value = "33336543"; float yourFloatData; char *special_ptr = (char *)(&yourFloatData); int i; int len = strlen(ModBus_value); if ( len == (sizeof(float)*2) ) { for (i=0; i<len; i+=2) { *special_ptr = ascii2bin(ModBus_value[i], ModBus_value[i+1]); special_ptr++; } printf("yourFloatData_1: %f\n", yourFloatData ); } else { printf("Wrong string\n"); } return 0; } Other implementation, less readale of getDigit should be: uint8_t getDigit ( uint8_t digit) { uint8_t retVal = 0; if ((digit >= '0') && (digit <= '9')) { retVal = digit - '0'; } else if ((digit >= 'A') && (digit <= 'F')) { retVal = digit - '7'; } else if ((digit >= 'a') && (digit <= 'f')) { retVal = digit - 'W'; } else { printf("Wrong char\n"); } return retVal; } Or uint8_t getDigit ( uint8_t digit) { uint8_t retVal = 0; if ((digit >= '0') && (digit <= '9')) { retVal = digit - '0'; } else if ((digit >= 'A') && (digit <= 'F')) { retVal = digit - 55; } else if ((digit >= 'a') && (digit <= 'f')) { retVal = digit - 87; } else { printf("Wrong char\n"); } return retVal; } Or uint8_t getDigit ( uint8_t digit) { uint8_t retVal = 0; if ((digit >= '0') && (digit <= '9')) { retVal = digit - '0'; } else if ((digit >= 'A') && (digit <= 'F')) { retVal = digit - 55; } else if ((digit >= 'a') && (digit <= 'f')) { retVal = digit - 87; } else { printf("Wrong char\n"); } return retVal; }