12
$\begingroup$

I have the image of a matrix (download it to see it bigger):

a matrix

Is there a way to convert this into a Mathematica numerical matrix, using Mathematica?

$\endgroup$
7
  • $\begingroup$ Do you know the bounds of the values of your matrix? Are they all 0/1/-1/2? $\endgroup$
    – rm -rf
    Jan 13, 2014 at 20:58
  • $\begingroup$ @rm-rf Yes. You can assume that the values are all in the set {-1, 0, 1, 2}. $\endgroup$
    – becko
    Jan 13, 2014 at 21:00
  • $\begingroup$ ImageCorrelate is probably your friend here. $\endgroup$
    – rm -rf
    Jan 13, 2014 at 21:02
  • $\begingroup$ Various methods are described here here. If you know the dimension of this matrix as well as how the columns are spatially distributed it might help, because a useful first step is probably to partition the image (and then use ImageCorrelate like rm -rf said). $\endgroup$
    – C. E.
    Jan 13, 2014 at 21:12
  • $\begingroup$ @anon You can also assume that you know the dimensions of the matrix. In this example, the matrix is 46x34. The columns and rows are clearly delineated in the image. $\endgroup$
    – becko
    Jan 13, 2014 at 21:19

2 Answers 2

10
$\begingroup$

TextRecognize works fine after some tweaks and error corrections:

x = Import["http://i.stack.imgur.com/NQr6I.png"];
res = TextRecognize[Binarize[ImageResize[x, Scaled[5]], 0.7],"SegmentationMode" -> 6];

m = ToExpression /@ StringSplit[#] & /@ 
   StringSplit[
    StringReplace[
     res, {"O" | "D" | "U" -> "0", "~" | "\"" -> "-", "I" -> "1"}], 
    "\n"];

m // MatrixForm

enter image description here

I have used the undocumented option "SegmentationMode" -> 6.

$\endgroup$
4
  • $\begingroup$ SegmentationMode details here $\endgroup$
    – Murta
    Jan 14, 2014 at 0:52
  • $\begingroup$ @Murta My last line is clickable with the same link :) $\endgroup$
    – ybeltukov
    Jan 14, 2014 at 0:56
  • $\begingroup$ +1 for proving that TextRecognize works. It seems the text needs to be large enough for it to work. $\endgroup$
    – shrx
    Jan 14, 2014 at 9:01
  • $\begingroup$ +1. But I've found one error: m[[28,28]] gives -1. It should be 1. $\endgroup$
    – becko
    Jan 14, 2014 at 14:32
11
$\begingroup$

Here is one way:

data = ColorNegate@Import@"http://i.stack.imgur.com/NQr6I.png";

points=ComponentMeasurements[ MorphologicalComponents[Sharpen[Dilation[Binarize@data,1.5],1]] ,"Centroid"][[All,2]];
box=ComponentMeasurements[ MorphologicalComponents[Sharpen[Dilation[Binarize@data,1.5],1]] ,"BoundingBox"][[All,2]];

{posX,posY}=Mean/@Split[#,If[Abs[#1-#2]<5,True,False]&]&/@{Sort@points[[All,1]],Sort@points[[All,2]]}

We can see that grid position worked in this plot:

ListPlot[points,PlotRange->All,GridLines->{posX,posY},PlotStyle->Red]

enter image description here

Now let's do image partition:

imagePartition = ParallelMap[ImageTrim[Binarize@data, #] &, box];

Here is a sample:

imagePartition[[;; 15]]

enter image description here

Now the part that has to be improved, here is one attempt to recognize the numbers.

getNumber[img_]:=Module[{r,comp},
    comp=ComponentMeasurements[img,{"PerimeterCount","Holes"}][[All,2]];
    r=Which[
            Length@#==2,-1
            ,#[[1,2]]==1,0
            ,#[[1,1]]<15,1
            ,True,2
        ]&[comp];
    (*{r,comp,img}*)
    r
]

Two elements finds -1, one hole find 0, no hole with perimeter < 15 finds 1 and the rest is 2.

Applying it data partition as:

numberData=Partition[ParallelMap[getNumber,imagePartition],Length@posX]//MatrixForm

We get:

Grid[numberData,Spacings->0,Alignment-> NumberPoint,Dividers->LightGray,BaseStyle->{FontSize-> 11}]

enter image description here

Not perfect, but can be a start point. It's just improve getNumber.

Update

With some calibration in getNumber and using Binarize intead of Sharpen, now all cases are ok.

$\endgroup$
3
  • 1
    $\begingroup$ Related to the last part: coming soon. First application example $\endgroup$
    – Rojo
    Jan 14, 2014 at 2:23
  • $\begingroup$ Yes I know! Tks for show that this documentation is already public :) $\endgroup$
    – Murta
    Jan 14, 2014 at 10:06
  • $\begingroup$ +1 But it has some mistakes. numberData[[6, 5]] and numberData[[6, 6]] both give 0, but should be -1 and 1 respectively. $\endgroup$
    – becko
    Jan 16, 2014 at 18:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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