8

I am developing an algorithm to generate a descriptor of a 2D object based on polar histogram. suppose that we have a datalist centered in {cx,cy}. I use 36 bins where I consider 12 angles and 3 different radius (see figure). I tried this code but I did not get the right figure. How can specify just 12 angles and how can we count the point of each sector?

data = {{10, 10}, {20, 20}, {40, 40}, {10, 20}, {100, 2}, {1, 1}, {2, 
    40}, {10, 11}, {12, 13}, {15, 15}, {100, 25}, {112, 12}, {113, 
    114}, {1, 111}};
center={50,50}
centereddata = (# - center) & /@ data;
angles = N[ArcTan[#[[1]], #[[2]]]/Degree] & /@ centereddata
radiis = N@Sqrt[#[[1]]^2 + #[[2]]^2] & /@ centereddata;
ListPolarPlot[Transpose[Join[{angles}, {radiis}]], PolarAxes -> True,
 PolarGridLines -> Automatic,PolarTicks -> {"Degrees", Automatic}]

enter image description here

BetterEnglish
  • 2,026
  • 13
  • 19
  • related http://mathematica.stackexchange.com/q/10923/193 – Dr. belisarius Dec 10 '14 at 04:28
  • 1
    related (duplicate?): (31347) – C. E. Dec 10 '14 at 04:38
  • @Pickett, thanks. This reference does not count the number of points of each sector. I think it is not possible to specify the number of angles using ListPolarPlot[]. I fond this example http://stackoverflow.com/questions/7419562/from-cartesian-plot-to-polar-histogram-using-mathematica using the ListPolarPlot[] but it did not specify the angles number. – BetterEnglish Dec 10 '14 at 05:06
  • What's radiis? It's not specified in your code. – Verbeia Dec 10 '14 at 05:51
  • @Verbeia, sorry I edited my code. – BetterEnglish Dec 10 '14 at 06:11
  • @Developer2000 My solution in that thread uses HistogramList to count the number of points in each slice. This is a one-dimensional binning, but HistogramList can also do two-dimensional binning so I think it should be able to count the number of points in each sector. (i.e. this is a different question than this one, but I think the same solution may apply.) – C. E. Dec 10 '14 at 11:05
  • @Pickett, my first issue is how to specify the number of angles and the number of raduis ListPolarPlot[]? – BetterEnglish Dec 10 '14 at 15:05

3 Answers3

10
 data = RandomReal[ {0, 200}, {200, 2}];
 center = {50, 50};
 centereddata = (# - center) & /@ data;
 angles = N[ArcTan[#[[1]], #[[2]]]/Degree] & /@ centereddata;
 radiis = N@Sqrt[#[[1]]^2 + #[[2]]^2] & /@ centereddata;

note you need to use Degree to put the angles back to radians here..

 polardata = Transpose[Join[{angles Degree}, {radiis}]];
 ListPolarPlot[polardata, PolarAxes -> True, 
    PolarGridLines -> Automatic, PolarTicks -> {"Degrees", Automatic}]

enter image description here

 bins = Table[a, {a, -180, 180, 30}];
 bincenters = ( Degree) Mean /@ Partition[ bins , 2, 1];
 hdata = Transpose[{bincenters , BinCounts[angles, {bins}] } ];
 ListPolarPlot[ hdata , PolarAxes -> True, PolarGridLines -> Automatic,
    PolarTicks -> {"Degrees", Automatic},
    Epilog -> {Red, 
    Line[{{0, 0}, #[[2]] {Cos[#[[1]]], Sin[#[[1]]]}}] & /@ hdata}]

enter image description here

ListPolarPlot doesn't evidently have a Filling option, hence the Epilog

... I hope you didn't just want this :)

   Histogram[ 1/Degree First /@ polardata  , {bins}]

enter image description here

edit a bit fancier..

 Epilog -> {Red, {Line[{{0, 0}, #[[2]] {Cos[#[[1]]], Sin[#[[1]]]}}], 
     Circle[{0, 0}, #[[2]], {#[[1]] - 15 Degree, #[[1]] + 15 Degree}]} & /@ 
     hdata}`

enter image description here

george2079
  • 38,913
  • 1
  • 43
  • 110
10

[Edited to correct the bin definition.]

You could use SectorChart. The trick is to ensure that your bin widths sum to 360° and that the first bin charted starts at zero.

Firstly, and borrowing shamelessly from @george2079's answer [and subsequent correction], define the bins:

bins = Table[a , {a, -180, 180, 30}];

Next create the sector chart data:

sData = RotateLeft[
  Tooltip[Join[Differences[#1], {#2}], {Mean[#1], #2}] & @@@ 
   Transpose[{Partition[bins, 2, 1], BinCounts[angles, {bins}]}], 
  FirstPosition[bins, 0] - 1]

{{30, 1}, {30, 8}, {30, 0}, {30, 0}, {30, 2}, {30, 1}, {30, 0}, {30, 1}, {30, 0}, {30, 0}, {30, 1}, {30, 0}}

There are several things going on here:

  • We add a tooltip so that the each sector is labelled with the mid-point of the bin and the count,
  • we calculate the width of each bin and
  • we rotate the data such that the bin starting at zero is first in the list. Obviously this requires a bin edge at zero.

Finally chart it, adding axes, etc. and rotating the origin (thanks again @george2079):

SectorChart[sData, PolarGridLines -> Automatic, 
 PolarTicks -> {Automatic, None}, PolarAxes -> {True, False}, 
 SectorOrigin -> 0]

Sector chart

MikeLimaOscar
  • 3,456
  • 17
  • 29
  • +1 nice, but you "shamelessly" copied my mistake :).. Also BTW SectorOrigin->0 will make this look more like a standard polar plot. – george2079 Dec 10 '14 at 20:02
  • @george2079 Thanks. I've corrected the bins in my answer too but it was slightly more involved because the sectors are relative. – MikeLimaOscar Dec 11 '14 at 10:05
4

I propose an example silhouette descriptor based on a polar histogram. In my example histogram consits of 36 bins.

enter image description here

newBinCounts funtion

newBinCounts[angles_, bins_] := Module[{hist, sectorIndex}, (
       hist = BinCounts[angles, {bins}];
       sectorIndex = 
        Table[Flatten[
          Union[Position[angles, #] & /@ 
            Select[angles, bins[[i]] <= # < bins[[i + 1]] &]]], {i, 1, 
          Length[bins] - 1}];
       {hist, sectorIndex}
       )]

polarHistogram function

polarHistogram[regionOfInterest_, anglebins_] := 
 Module[{positionsWhitePixel, centroid, centeredpositionsWhitePixel, 
   angles, bins, raduis, bincenters, histData, sectorIndex, hData, 
   binrad, listOfRadius, listHist}, (

   positionsWhitePixel = 
    PixelValuePositions[regionOfInterest, White];

   Graphics[{Point@positionsWhitePixel}];

   centroid = N@Mean[positionsWhitePixel];


   centeredpositionsWhitePixel = (# - centroid) & /@ 
     positionsWhitePixel;

   angles = 
    Mod[(# + 360), 360] & /@ (N[ArcTan[#[[1]], #[[2]]]/Degree] & /@ 
       centeredpositionsWhitePixel);
   raduis = 
    N@Sqrt[#[[1]]^2 + #[[2]]^2] & /@ centeredpositionsWhitePixel;

   Print[ListPolarPlot[Transpose[Join[{angles Degree}, {raduis}]], 
     PolarAxes -> True, PolarGridLines -> Automatic, 
     PolarTicks -> {"Degrees", Automatic}]];

     bins = Table[i, {i, 0, 360, anglebins}];
   bincenters = (Degree) Mean /@ Partition[bins, 2, 1];
   {histData, sectorIndex} = newBinCounts[angles, bins];
   hData = Transpose[{bincenters, BinCounts[angles, {bins}]}];

   Print[ListPolarPlot[hData, PolarAxes -> True, 
     PolarGridLines -> Automatic, 
     PolarTicks -> {"Degrees", Automatic}, 
     Epilog -> {Red, 
       Line[{{0, 0}, #[[2]] {Cos[#[[1]]], Sin[#[[1]]]}}] & /@ hData}]]
   (*in this code, i consider 3 raduis 0-20,
   20-40,40,200*)
   binrad = {0, 20, 40, 200};
   listOfRadius = raduis[[#]] & /@ sectorIndex;
   listHist = Transpose[BinCounts[#, {binrad}] & /@ listOfRadius];
   listHist
   )]

This function calculate an histogram of 36 bins. (call function using the silhouette)

list3 = polarHistogram[sil3, 30];


 (*list3={{100,103,104,107,104,99,111,104,106,103,104,111},{309,316,311,263,303,309,319,313,316,314,314,319},{1325,2079,132,0,45,359,1741,1674,514,148,53,176}}*)

enter image description here enter image description here

\ https://i.stack.imgur.com/aZmWQ.png

BetterEnglish
  • 2,026
  • 13
  • 19