I try to implement OCR in a really noisy image. There is also a low contrast between the number and background. I have tried to use some median filter to smooth background noise and edge enhancement method but without sensible effect. Does anyone have something similar task to do? What filter should I use?
Number with background's noise and low contrast:
EDIT (ADDED OVEREXPOSED PICTURES)
If you are able to do the image acquisition again there are few options:
Try to overexpose the image, which might have a positive effect on the segmentation of number from the background. I just wrote a post about it: https://www.linkedin.com/pulse/making-overexposure-work-you-part-i-vladimir-perkovic
Since you have the Halcon tag, I assume you have access to Halcon. Take a look at example ocr_embossed_photometric_stereo.hdev which shows how to read embossed letter using lights from multiple directions.
In case that you have to work with only existing images the best I've got is using the Maximally Stable Extremal Regions (MSER) in Halcon:
rgb1_to_gray (Image, GrayImage)
segment_image_mser (GrayImage, MSERDark, MSERLight, 'dark', 600, 60000, 1, 'may_touch_border', 'false')
Actually this shared images' resolutions are very low (nearly 190x160). If real images' resolutions are higher than this images, you can get better results. I tried some codes on images. I found digits as "6" and "&".
Screenshot is here:
https://drive.google.com/open?id=1I1s79hwcon8IdxC6peRxMbaB4I2taNFr
Code is here:
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 18, 'mono', 'true', 'false')
**reading image
read_image (Pnk9h, '/home/emin/Desktop/pNk9h.png')
get_image_size (Pnk9h, Width, Height)
**bluring image but preserve the edges
bilateral_filter (Pnk9h, Pnk9h, ImageBilateral, 9, 10, [], [])
**sharpening image
emphasize (ImageBilateral, ImageEmphasize, 7, 7, 5)
**processes about finding digits
var_threshold (ImageEmphasize, Region, 150, 150, 0.2, 2, 'dark')
var_threshold (ImageEmphasize, Region2, 150, 150, 0.2,5, 'light')
fill_up (Region, RegionFillUp)
difference (RegionFillUp, Region, RegionDifference)
opening_circle (RegionFillUp, RegionOpening, 3.5)
connection (RegionOpening, ConnectedRegions)
sort_region (ConnectedRegions, SortedRegions, 'first_point', 'true', 'column')
select_shape (SortedRegions, SelectedRegions, ['area','row','row1','row2'], 'and', [150,Height/2-20,10,0], [99999,Height/2+20,Height,Height-10])
smallest_rectangle1 (SelectedRegions, Row1, Column1, Row2, Column2)
gen_rectangle1 (Rectangle, Row1, Column1, Row2, Column2)
intersection (Rectangle, Region, RegionIntersection)
opening_circle (RegionIntersection, RegionOpening1, 2)
area_center (RegionOpening1, Area, Row, Column)
union1 (RegionOpening1, RegionUnion)
**painting image for reading robustly
paint_region (RegionUnion, ImageEmphasize, ImageResult, [0,0,0], 'fill')
complement (RegionUnion, RegionComplement)
paint_region (RegionComplement, ImageResult, ImageResult, [255,255,255], 'fill')
**reading digits
read_ocr_class_cnn ('Universal_0-9+_NoRej.occ', OCRHandle3)
do_ocr_multi_class_cnn (SelectedRegions, ImageResult, OCRHandle3, Class3, Confidence3)
dev_disp_text (Class3, 'image', Row2+10, Column2-50, 'blue', [], [])
I noticed that this code doesn't quite work as expected on iOS 11, because the "adjustedContentInset" property value changes as the "navigationBar" shrinks during a scroll:
CGFloat contentInsetTop=[scrollView contentInset].top;
if (#available(iOS 11.0, *))
{
contentInsetTop=[scrollView adjustedContentInset].top;
}
////
[scrollView setContentOffset:CGPointMake(0, -contentInsetTop) animated:YES];
... For example, this might start out as 140, then reduce to 88 beyond a minimal scroll offset. This means if you call this, it doesn't actually scroll all the way to the top.
Aside from preserving the original offset in memory from when the UIScrollView loads, is there a way to recover this value later to ensure that it does indeed scroll to top consistently, no matter the "adjustedContentInset"?
Currently, there is indeed no way to do this with iOS 11, I have heard. The only way to do so is to capture the initial value and store it for the life of the navigation/view controller.
I will update my answer accordingly if I hear otherwise, but it will be broken in the base iOS 11 release forever unfortunately.
I had this same problem with a Large Title in iOS 11, and the following code worked for me.
The following code first scrolls the offset a reasonable size above where you want to be. The value -204.666666666667 was the tallest value from setting the Accessibility > Larger Text > Larger Accessibility Sizes to the highest. I'm sure this doesn't cover other possibilities, but it is working for me so far. -CGFloat.greatestFiniteMagnitude is otherwise too problematic.
tableView.setContentOffset(CGPoint(x: 0.0, y: -204.666666666667), animated: false)
This will now give you back the right adjusted content size. To avoid being scrolled too far higher, i.e. leaving white space, just use the value as follows.
var contentOffset = CGPoint.zero // Just setting a variable we can change as needed below, as per iOS version.
if #available(iOS 11, *) {
contentOffset = CGPoint(x: 0.0, y: -tableView.adjustedContentInset.top)
} else {
contentOffset = CGPoint(x: 0.0, y: -tableView.contentInset.top)
}
tableView.setContentOffset(contentOffset, animated: false)
In summary, set the offset higher first (-204.666666666667 in my case, or just -300 or whatever), then that readjusts the adjustedContentInset.top to include the Large Title, scroll bar, etc., then you can now set the content offset as needed.
The goal: Have a scroll view that displays an array of uiimageviews (photos) that you can horizontally scroll through them
How I understand to do this: Make the frame (CGRect) of each uiimageview the height and width of the scroll view, the y value to 0 on each, and set the first imgViews x value to 0. For every imgView after that, add the width of the scrollview to the x value. In theory, this would line the imgViews (Photos) up next to each other horizontally and not allow for any vertical scrolling or zooming, purely a horizontal photo viewer.
The storyboard setup: I am creating my scrollview in a xib file (It’s a custom uiCollectionViewCell), with these constraints:
— Top space to cell (0)
— Trailing space to cell (0)
— Leading space to cell (0)
— Height of 400
— Bottom space to a view (0)
—— (See Below for img)
Laying out the UIImgViews:
func layoutScrollView() {
for (index, img) in currentImages.enumerate() {
let imgView = UIImageView(frame: CGRect(x: CGFloat(index) * scrollView.bounds.width, y: CGFloat(0), width: scrollView.bounds.width, height: scrollView.bounds.height))
imgView.contentMode = .ScaleAspectFill
imgView.image = img
scrollView.addSubview(imgView)
scrollView.contentSize = CGSize(width: imgView.frame.width * CGFloat(index), height: scrollView.bounds.height)
scrollView.setNeedsLayout()
}
}
My suspicion: I suspect the issue is stemming from the auto layout constraints i’ve specified, but (considering Im asking a SO question) not sure
If there is a better way to do this (really the correct way) please let me know! I have been trying to wrap my head around this for a few days now.
I appreciate all responses! Thanks for reading
EDIT #1
I tried paulvs approach of setting setNeedsLayout & layoutIfNeeded before the "for" loop, and still no luck. Here is (out of three images selected) the second photo displaying. It seems that both the first and second photos are way longer than the content view and that would move the middle view over (Squished).
Your code looks fine except for a few details (that may be causing the problem):
Add:
view.setNeedsLayout()
view.layoutIfNeeded()
before accessing the scrollView's frame (a good place would be before the for-loop).
This is because when using Autolayout, if you access a view's frame before the layout engine has performed a pass, you will get incorrect frames sizes/positions.
Remove these lines from inside the for-loop:
scrollView.contentSize = CGSize(width: imgView.frame.width * CGFloat(index), height: scrollView.bounds.height)
scrollView.setNeedsLayout()
and place this line after (outside) the for loop:
scrollView.contentSize = CGSize(width: imgView.frame.width * CGFloat(currentImages.count), height: scrollView.bounds.height)
I am animating the height change of a NSTableView based row. I am using noteHeightOfRowsWithIndexesChanged for that row to reduce the height by -
NSAnimationContext.runAnimationGroup({ (context: NSAnimationContext) -> Void in
context.duration = 0.5
self.table.noteHeightOfRowsWithIndexesChanged(NSIndexSet(index: rowIndex!))
}, completionHandler: nil)
This works perfectly when the row has a small size and the row's full frame is visible.
If the row height is tall and the row frame is not completely visible, it causes an issue: the reload of multiple rows, breaking the smooth height reduce animation and causing a lot of flickering.
What is the correct way of reducing the height of a row that has a big height(with animation)?
I want to set a minimum height on a stacked bar so that it always shows no matter how small the value.
Example:
If the stacked values are relatively close, the bars show no problem:
http://i41.tinypic.com/b88rc6.png
But if the values differ by a lot, then the smaller bar is not visible on the graph:
http://i40.tinypic.com/15rxwz6.png
I tried reading through the docs but didn't find any options for this. Help is appreciated!
Try to assing the smaller values to an other yaxis, so the graph will show 2 different yaxes, the first with a big interval, the second with an interval that permits to show correctly the smaller values (if you want to show the difference between the two kind of data, you could use min and max on the smaller yaxis).
axes: { [...], yaxes: { -big values- }, y2axes: { -small values-, min: -10, max: 10 }}
Don't know if that answer would be useful to you.