2
$\begingroup$

enter image description here

I want to count how many grids in colunm and row,I know the answer is 38*11,But how can I use mma to count it?It confusion me to think it long.

$\endgroup$
11
  • $\begingroup$ Maybe MorphologicalComponents? $\endgroup$
    – march
    Sep 20, 2015 at 23:04
  • $\begingroup$ As I know.I don't think MorphicalComponents is a good way. $\endgroup$
    – yode
    Sep 20, 2015 at 23:08
  • $\begingroup$ Have you looked at ImageLines? $\endgroup$
    – MarcoB
    Sep 20, 2015 at 23:14
  • $\begingroup$ I have a try with ImageLine just,But the effect is too shy,thinks for your hint anyway. $\endgroup$
    – yode
    Sep 20, 2015 at 23:23
  • 1
    $\begingroup$ @yode You have accepted none of the answers to your questions. Does it mean that you are not satisfied with any of them (as it is should be interpreted according to the philosophy of this site) or you just do not know for what there is the green checkmark at the left of every answer? $\endgroup$ Sep 21, 2015 at 6:25

2 Answers 2

7
$\begingroup$
i = Import["https://i.stack.imgur.com/XKqb1.png"];
iD = ImageData[i, Automatic];

Let us look at the first row in the image:

Short[iD[[1, ;;]], 5]
{{220,220,220,255},{254,254,254,255},{252,252,252,255},{252,252,252,255},{252,252,252,255},
{238,238,238,255},{225,225,225,255},{252,252,252,255},{252,252,252,255},{252,252,252,255},
{252,252,252,255},{246,246,246,255},{221,221,221,255},<<210>>,{238,238,238,255},{252,252,252,255},
{252,252,252,255},{252,252,252,255},{252,252,252,255},{231,231,231,255},{231,231,231,255},
{252,252,252,255},{252,252,252,255},{252,252,252,255},{252,252,252,255},{249,249,249,255}}

We see that all the pixels have equal the R,G,B channel values and most of the pixels have {R,G,B,Alpha} channel values {252,252,252,255} - it is the background. Other pixels mostly have darker colors - they represent the grid lines, brighter pixels are due to anti-aliasing applied to the grid lines and they always are adjacent to the darker pixels. It is important that the first and the last pixels are darker - it means that there probably were also grid lines which were cropped and for the last grid line we have only the adjacent line due to anti-aliasing which is only a little darker than the background.

Considering that the R,G,B channel values are equal, we may take only first of them and then split the list by the criterion of whether the color is darker than 252 or not:

ListLinePlot[iD[[1, ;; , 1]], Filling -> {1 -> 255}, AspectRatio -> 1/10, 
 ImageSize -> 700]
Length /@ SplitBy[iD[[1, ;; , 1]], # < 252 &]

plot

{1, 4, 2, 4, 2, 5, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 3, 4, 2, 
4, 2, 4, 2, 4, 2, 4, 2, 5, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 2, 4, 3, 
4, 2, 4, 2, 4, 2, 4, 2, 4, 3, 4, 2, 4, 2, 4, 2, 4, 1}

We see that the background pixels mostly occur in groups of 4 successive pixels while the grid lines occur in groups of 2 - 3 pixels with only exception for the first and the last grid lines. Now we can simply count the grid lines:

Count[SplitBy[iD[[1, ;; , 1]], # < 252 &], {c_ /; c < 252, ___}] 
39

We counted 39 grid lines with the last represented by the bordering pixels which arose due to antialiasing and visually are almost indistinguishable from the background. Whether the latter should be counted as a grid line is up to you. The following subtle change of the grouping criterion and the counting criterion discards it from the count:

Count[SplitBy[iD[[1, ;; , 1]], # == 252 &], {c_ /; c != 252, __}]
38

So we have found that the first row contains 38 easily visually distinguishable vertical grid lines.

Application of this procedure for determination of the number of horizontal grid lines I left for you as an exercise. The only note: don't take for the analysis the first two columns because they belong to the first vertical grid line.

Have fun!


P.S. Only after writing this I realized that the first row is also affected by the anti-aliasing applied to a horizontal grid line which was later cropped. If we take for the analysis the second or the third row of the image the procedure simplifies:

Count[SplitBy[iD[[3, ;; , 1]], # == 255 &], {c_ /; c < 255, ___}]
39

But now it becomes even lesser obvious whether we should count the last (almost visually indistinguishable from the background) vertical grid line or not: both the first and the last vertical grid line have widths only one pixel and differ from the background much stronger than in the case of above analysis performed for the first row of the image:

ListLinePlot[iD[[3, ;; , 1]], Filling -> {1 -> 255}, AspectRatio -> 1/10, 
 ImageSize -> 700]
Short[iD[[3, ;; , 1]]]

plot2

{231,255,255,255,255,236,217,255,255,255,255,247,211,255,
<<207>>,255,217,236,255,255,255,255,226,225,255,255,255,255,248}

In such situation it is preferred to count either both or none of them as actual vertical grid lines. If you prefer the latter, proceed using the following modification of the counting criterion:

Count[SplitBy[iD[[3, ;; , 1]], # == 255 &], {c_ /; c < 255, __}]
37

UPDATE

A curious fact: the gray pixels create some interesting periodical pattern when plotted:

ListPlot[iD[[3, ;; , 1]], AspectRatio -> 1/10, ImageSize -> 700]

plot3

By taking every second pixel we can make the pattern more evident:

indexedList = MapIndexed[{#2[[1]], #1} &, iD[[3, ;; , 1]]];
ListPlot[{indexedList[[;; ;; 2]], indexedList[[2 ;; ;; 2]]}, AspectRatio -> 1/10, 
 ImageSize -> 700]

plot4

Looks very similar to Abs[Sin[x]], isn't it?

lst1 = DeleteCases[indexedList[[;; ;; 2]], {_, 255}];
ListPlot[lst1, AspectRatio -> 1/10, ImageSize -> 700]
Plot[45 (1 - Abs[Sin[x/21 + .7]]) + 210, {x, 0, 235}, AspectRatio -> 1/10, 
 ImageSize -> 700]

plot5 plot6

Let us try to fit the model to the data without edge points:

model = scY (1 - Abs[Sin[x/scX + shX]]) + shY;
nlm = NonlinearModelFit[lst1[[2 ;; -2]], 
   model, {{shX, .7}, {shY, 210}, {scY, 45}, {scX, 21}}, x];
Plot[nlm[x], {x, 0, 235}, Epilog -> Point@lst1]
ListPlot[Table[{p[[1]], Abs[p[[2]] - nlm[p[[1]]]]}, {p, lst1}], PlotRange -> All, 
 Filling -> {1 -> Axis}]

plot7 plot8

I'm not sure how this pattern has to be explained but both edge values fall out of the regularity. It supports the decision do not count them.

$\endgroup$
1
$\begingroup$

I have somethint to share,With the help of @AlexeyPopkov ,I can do it right now like this:

list1 = ImageData[
    ColorConvert[pic // RemoveAlphaChannel, "Grayscale"], Automatic][[
   1]];
Split[list, Abs[# - 252] <= 4 &] // 
  Select[#, Length[#] != 1 &] & // Length
(*38*)

list2 = ImageData[
    ColorConvert[pic // RemoveAlphaChannel, "Grayscale"], Automatic][[
   All, -1]];
Split[list, Abs[# - 252] <= 4 &] // 
  Select[#, Length[#] != 1 &] & // Length
(*11*)

But I think a another way to solve it,the code is that:

pic1 = MorphologicalBinarize[pic // ColorNegate, 0.08] // ColorNegate;
pic2 = MorphologicalComponents[pic, 0.04] // Colorize // Binarize // 
   ColorNegate;
pic3 = ImageAdd[pic2, pic1];
pic3 // ComponentMeasurements[#, "Centroid"] & // 
 Show[pic3, 
   Graphics[{Blue, 
     MapIndexed[Inset[Style[#2[[1]], 8], #1] &, #[[All, 2]]]}]] &

the result is:enter image description here

Anyway thanks anybody.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.