Amazon Textract Bounding box co-ordinates changing for a particuleat block - coordinates

I am using Amazon Textract for Text detecting or Raw text, forms and Tables.
I am uploading a PDF for that.
I am using co-ordinates to get the value from raw text. I was successful in getting the value.
But after some days, the bounding box co-ordinates for that particular block changed. Then, my logic was not working.
Do you guys have any idea why those co-ordinates are changing?
This is how I have applied my logic after identifying the co-ordinates.
if ((item.Geometry.BoundingBox.Top >= 0.92379182 && item.Geometry.BoundingBox.Top <= 0.96)
&& (item.Geometry.BoundingBox.Left >= 0.02470588 && item.Geometry.BoundingBox.Left <= 0.29)
&& (item.Geometry.BoundingBox.Height >= 0.001 && item.Geometry.BoundingBox.Height <= 0.054545)
&& (item.Geometry.BoundingBox.Width >= 0.001 && item.Geometry.BoundingBox.Width <= 0.16))
{
text = text + " " + item.Text;
}

The machine learning models behind Textract are subject to change. Although there are regression tests in place to ensure the overall quality doesn't get worse, that's not to say the results won't ever change. Especially things like bounding boxes, as long as the region of interests are still bounded correctly, slightly change in coordinates may not be considered as a regression.

Related

When a new pivot point is found, how can i compare the value with the previous one?

If a pivothigh is calculated using "ta.pviothigh" in pinescript_v5
Can we use pH[1] to indicate the previous pivot high or how can I get the value of the previous one when a new pivot high is found? As I want to check whether the close price of the new found pivot high is higher or lower than the previous pivot high.
I tried the script below and ran it:
pH = ta.pivothigh (close, 5, 5)
pH_fall = pH < pH[1]
plotshape (pH, "pH", shape.triangledown, color=color.aqua, size=size.tiny)
plotshape (pH_fall, "fall", shape.xcross, color=color.black, size=size.small)
It didn't say there is any mistake in the script but it just not showing the black Xcross that should be indicating a falling pivothigh. How should I amend it?

How to enhance Tesseract automatic text rotation capabilities for OCR?

I have a set of PIL images, where some pages are correctly rotated, while others have a rotation close to 180°. This means that automatic orientation detection may fail as instead of 178° degrees recognizes a 2° degrees orientation.
Unfortunately, Tesseract sometimes cannot understand the difference between 2° orientation and 178°, so in the latter case, the output is completely wrong.
A simple im.rotate(180) automatically fixes this, but the step is manual, and I would like tesseract to automatically understand whether the text is upside-down or not.
Looking at some approaches they require the Hough transform for understanding of the prevalent orientation in the document. In this case, however, they may fail, because of the peculiar orientation of these scanned documents.
What options for automatic rotation are available, without reyling on third party scripts, but staying within Python libraries?
I am new to StackOverflow, so please forgive me for any kind of misleadings or incorrect answers. In case if anyone is still looking for an answer, pytesseract's image_to_osd function gives the information about the orientation. It only determines the orientation as 0°,90°,180° or 270° i.e. it accurately determines the orientation if the text is aligned along with the axes. But it also outputs any of those four angles even for a different orientation.
So if you are working with minute angle differences like 2° or so, this should solve the issue. So first we align the text and then use the function.
here is the code in python:
while True:
osd_rotated_image = pytesseract.image_to_osd(image)
# using regex we search for the angle(in string format) of the text
angle_rotated_image = re.search('(?<=Rotate: )\d+', osd_rotated_image).group(0)
if (angle_rotated_image == '0'):
image = image
# break the loop once we get the correctly deskewed image
break
elif (angle_rotated_image == '90'):
image = rotate(image,90,(255,255,255)) # rotate(image,angle,background_color)
continue
elif (angle_rotated_image == '180'):
image = rotate(image,180,(255,255,255))
continue
elif (angle_rotated_image == '270'):
image = rotate(image,90,(255,255,255))
continue
And to align the text deskew python library is the best in my opinion.
Thank you.

How to get region with lowest y value in the centroid

I have a binary image that has two connected components. Both are fairly horizontal and one is on the top of the image and the other at the bottom. What I need to do is to extract only the top component which I want to do (or at least what I think is a good method) by taking the component with the lowest y value for the centroid (because MATLAB uses Java to show images, so the origin is at the top left) and erasing the other component. So far I've been able to use regionprops to find which region has the lowest y value for the centroid, but from there I'm not sure how to get a binary image back again with the component I want.
I've read in the documentation that bwconncomp, labelmatrix, and ismember are useful, but I'm not very sure how to use them well (or at all very much).
This is the solution I just made up, but if there's a better or more elegant one I'd love to know about it!
P.S. filtered is my image
connComp = bwconncomp(filtered);
props = regionprops(filtered, 'Centroid');
justTop = zeros(size(filtered,1), size(filtered,2));
if props(1).Centroid(2) > props(2).Centroid(2)
justTop(connComp.PixelIdxList{2}) = 1;
else
justTop(connComp.PixelIdxList{1}) = 1;
end`

VL_SLIC MATLAB Output for VL_FEAT

I am using the VL_SLIC function in MATLAB and I am following the tutorial for the function here: http://www.vlfeat.org/overview/slic.html
This is the code I have written so far:
im = imread('slic_image.jpg');
regionSize = 10 ;
regularizer = 10;
vl_setup;
segments = vl_slic(single(im), regionSize, regularizer);
imshow(segments);
I just get a black image and I am not able to see the segmented image with the superpixels. Is there a way that I can view the result as shown in the webpage?
The reason why is because segments is actually a map that tells you which regions of your image are superpixels. If a pixel in this map belongs to ID k, this means that this pixel belongs to superpixel k. Also, the map is of type uint32 and so when you try doing imshow(segments); it really doesn't show anything meaningful. For that image that is seen on the website, there are 1023 segments given your selected parameters. As such, the map spans from 0 to 1023. If want to see what the segments look like, you could do imshow(segments,[]);. What this will do is that the region with the ID of 1023 will get mapped to white, while the pixels that don't belong to any superpixel region (ID of 0), gets mapped to black. You would actually get something like this:
Not very meaningful! Now, to get what you see on the webpage, you're going to have to do a bit more work. From what I know, VLFeat doesn't have built-in functionality that shows you the results like what is seen on their webpage. As such, you will have to write code to do it yourself. You can do this by following these steps:
Create a map that is true that is the same size as the image
For each superpixel region k:
Create another map that marks true for any pixel belonging to the region k, and false otherwise.
Find the perimeter of this region.
Set these perimeter pixels to false in the map created in Step #1
Repeat Step #2 until we have finished going through all of the regions.
Use this map to mask out all of the pixels in the original image to get what you see in the website.
Let's go through that code now. Below is the setup that you have established:
vl_setup;
im = imread('slic_image.jpg');
regionSize = 10 ;
regularizer = 10 ;
segments = vl_slic(single(im), regionSize, regularizer);
Now let's go through that algorithm that I just mentioned:
perim = true(size(im,1), size(im,2));
for k = 1 : max(segments(:))
regionK = segments == k;
perimK = bwperim(regionK, 8);
perim(perimK) = false;
end
perim = uint8(cat(3,perim,perim,perim));
finalImage = im .* perim;
imshow(finalImage);
We thus get:
Bear in mind that this is not exactly the same as what you get on the website. I simply went to the website and saved that image, then proceeded with the code I just showed you. This is probably because the slic_image.jpg image is not the exact original that was given in their example. There seems to be superpixels in areas where there are some bad quantization artifacts. Also, I'm using a relatively old version of VLFeat - Version 0.9.16. There may have been improvements to the algorithm since then, so I may not be using the most up to date version. In any case, this is something for you that you can start with.
Hope this helps!
I found these lines in vl_demo_slic.m may be useful.
segments = vl_slic(im, regionSize, regularizer, 'verbose') ;
% overaly segmentation
[sx,sy]=vl_grad(double(segments), 'type', 'forward') ;
s = find(sx | sy) ;
imp = im ;
imp([s s+numel(im(:,:,1)) s+2*numel(im(:,:,1))]) = 0 ;
It generates edges from the gradient of the superpixel map (segments).
While I want to take nothing away from ~ rayryeng's ~ beautiful answer.
This could also help.
http://www.vlfeat.org/matlab/demo/vl_demo_slic.html
Available in: toolbox/demo

Efficient way of making checkers from connected components

I have a binary image of several connected components, some large and some small (maybe only 1 pixel). With this I am seeking a way to make each connected component into a checkers pattern, instead of the connected blobs, in an efficient way.
So far I have come up with two ways this could be tried, but they can either produce errors, or be quite unefficient:
I know the entire image and can make a checkers pattern mask to remove 50% of the pixels. This is very fast, but will on average remove 50% of the connected components which are only one pixel in area.
Use bwlabel() in MATLAB/Octave, and loop through each connected component only applying the mask to that component if it is over 1 pixel (while leaving the other components to be considered when the loop gets to them). This can be very inefficient.
Any smart/built-in solutions which could be used?
Code to generate figure
T = zeros(40,40);
T(10:30,10:30) = 1;
chessVec = repmat([1;0],20,1);
T_wanted = (repmat([chessVec circshift(chessVec,1)],1,20).*T);
figure();
subplot(1,2,1);imshow(T);title('Start shape')
subplot(1,2,2);imshow(T_wanted);title('Wanted shape');
Nothing beats blanket checkering for efficiency. All you then need to do is add back the small connected components.
%# create a test image
img = rand(100)>0.8;
img = imclose(img,ones(5));
img = imerode(img,strel('disk',2));
%# get connected components
%# use 4-connect to preserve
%# the diagonal single-pixel lines later
cc = bwconncomp(img,4)
%# create checkerboard using one of Matlab's special matrix functions
chk = invhilb(100,100) < 0;
%# checker original image, add back small stuff
img(chk) = 0;
smallIdx = cellfun(#(x)x<2,cc.PixelIdxList);
img([cc.PixelIdxList{smallIdx}]) = 1;