reduce jagged edges and output perfect alphabet - python

I have a input image:
I am normalising the image and then binarising it using OTSU.
import cv2
import numpy as np
import sys
import os
import time
import imutils
import numpy as np
from matplotlib import pyplot as plt
import re
import math
orgImg = cv2.imread(sys.argv[1])
orgHeight,orgWidth,_ = orgImg.shape
image = imutils.resize(orgImg,height=350)
rheight, rwidth,_= image.shape
kernel = np.ones((7,7), np.uint16)
# image = cv2.erode(image, kernel, iterations=1)
image11 = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Copy image to new variable
g = image11.copy()
cv2.normalize(g, g, 70, 255, cv2.NORM_MINMAX)
ret,black_mask = cv2.threshold(g,110,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow("image",black_mask)
cv2.imwrite(sys.argv[1]+"thresh.jpg",black_mask)
cv2.waitKey(0)
The output image is:
In the output there are many jagged edges. How do I remove these edges and get a perfect "Ca"?
Output should be something like this:
P.S. Please note that the output image does not necessarily has to be binary

If you leave out the resize with imutils, the result will look like this:
I'm not sure where the extra black lines in your output image come from, because they are not created when I run you're code directly.
I changed around your code and cleaned it up a bit, it now looks like this:
import cv2
import numpy as np
from PIL import Image
orgImg = cv2.imread("ca.png")
image11 = cv2.cvtColor(orgImg, cv2.COLOR_BGR2GRAY)
cv2.normalize(image11, image11, 70, 255, cv2.NORM_MINMAX)
ret, black_mask = cv2.threshold(image11, 110, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow("Original image", orgImg)
cv2.imshow("Final image", black_mask)
cv2.waitKey(0)
cv2.imwrite("ca_blackmask.png", black_mask)

Related

Convert series of images into an array using OpenCV and convert the RGB array to gray scale

Hi I'm trying to convert a series of images into an array and then convert the RGB to gray scale.
In my work folder I have x number of frames.png, I need to read all this frames in an array and then convert each frame (RGB) to Gray scale.
For one frame my code is:
import numpy as np
import cv2 as cv
from PIL import Image
# Read image
Image = cv.imread('frame0.png')
# RGB to Gray Scale
GS = cv.cvtColor(Image, cv.COLOR_BGR2GRAY)
th, Gray = cv.threshold(GS, 128, 192, cv.THRESH_OTSU)
Any idea?
You can use os to read files from a folder. With the "endswith" function, you can extract file formats and pull them all.
Here is a working code
import numpy as np
import cv2 as cv
import os
for file in os.listdir("/mydir"): # images folder path
if file.endswith((".png",".jpg")): # you can add formats
img = cv.imread(file)
GS = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
th, Gray = cv.threshold(GS, 128, 192, cv.THRESH_OTSU)
cv.imwrite("converted-"+file,Gray)

How to color the circles on a thresholded image in python

I created a code to isolate big circles (white) and I would like to color those circles and create contours on the thresholded image to calculate area.
The thing is the threshold image is a binary image 8uint. How can do that in a binary imagee ?
Thanks for the help
import os
#from skimage import measure, io, img_as_ubyte
from skimage.color import label2rgb, rgb2gray
from skimage.segmentation import clear_border
import matplotlib.pyplot as plt
import numpy as np
import cv2
import pandas as pd
import sys
import glob
original = cv2.imread('D:/2022/Python program/NBC_new2022_/images/image1.jpg',-1)
original = cv2.resize(original, (864, 648)) #resize of original image
img = cv2.cvtColor(original, cv2.COLOR_BGR2GRAY)
median = cv2.medianBlur(img, 3)
ret, th = cv2.threshold(median, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((9,9), np.uint8)
opening = cv2.morphologyEx(th, cv2.MORPH_OPEN, kernel)
edge_touching_removed = clear_border(opening)
cv2.imshow('original', original)
cv2.imshow("Theshrold image", edge_touching_removed)
cv2.waitKey(0)
cv2.destroyAllWindows()

Remove background

I am doing OCR to extract information from the ID card. However, accuracy is quite low.
My assumption is that removing the background will make OCR more accurate.
I use the ID scanner machine (link) to obtain the grey image below. It seems that the machine uses IR instead of image processing.
Does anyone knows how to get the same result by using Opencv or tools (photoshop, gimp, etc)?
Thanks in advance.
Here are two more methods: adaptive thresholding and division normalization.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread("green_card.jpg")
# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# do adaptive threshold on gray image
thresh1 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 51, 25)
# write results to disk
cv2.imwrite("green_card_thresh1.jpg", thresh1)
# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_RECT , (11,11))
morph = cv2.morphologyEx(gray, cv2.MORPH_DILATE, kernel)
# divide gray by morphology image
division = cv2.divide(gray, morph, scale=255)
# threshold
thresh2 = cv2.threshold(division, 0, 255, cv2.THRESH_OTSU )[1]
# write results to disk
cv2.imwrite("green_card_thresh2.jpg", thresh2)
# display it
cv2.imshow("thresh1", thresh1)
cv2.imshow("thresh2", thresh2)
cv2.waitKey(0)
Adaptive Thresholding Result:
Division Normalization Result:
EDIT:
since there are different lighting conditions, contrast adjustment is added here.
The simple approache in my mind to solve your issue is that: since the undesired background colours are Green and Red, and the desired font colour is Black, simply suppress the Red and green colours as following:
import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread, imsave
from skimage.color import rgb2gray
from skimage.filters import threshold_otsu
from skimage import exposure
def adjustContrast(img):
p2, p98 = np.percentile(img, (2, 98))
img_rescale = exposure.rescale_intensity(img, in_range=(p2, p98))
return img_rescale
# Read the image
img = imread('ID_OCR.jpg')
# Contrast Adjustment for each channel
img[:,:,0] = adjustContrast(img[:,:,0]) # R
img[:,:,1] = adjustContrast(img[:,:,1]) # G
img[:,:,2] = adjustContrast(img[:,:,2]) # B
# # Supress unwanted colors
img[img[...,0] > 100] = 255 # R
img[img[...,1] > 100] = 255 # B
# Convert the image to graylevel
img = rgb2gray(img)
# Rescale into 0-255
img = 255*img.astype(np.uint8)
# Save the results
imsave('Result.png', img)
The image will look like:
The Results are not optimal, because also your image resolution isn't high.
At the end, there are many solutions, and improvements, also you can use Morphology to make it look nicer, this is just a simple proposal to solve the problem.

How to detect width of object in picture

I must write the program to detect width of object. I understand that without reference object it will be expressed in pixels but it's enough for me. The background will always be white. I have problem what i should to do right now.
I will be sow greatfull for Your help !
enter image description here
import numpy as np
import imutils
import cv2
import math
# Function to show array of images (intermediate results)
def show_images(images):
for i, img in enumerate(images):
cv2.imshow("image_" + str(i), img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Read image and preprocess
image = cv2.imread('44.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (9, 9), 0)
edged = cv2.Canny(blur, 50, 100)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)
show_images([blur, edged])
#show_images([cnts, edged])
Welcome to Stack Overflow!
Since your're using OpenCV, finding the image dimensions is as simple as the code below.
import numpy as np
import cv2
img = cv2.imread('image.png')
dimension = img.shape
height = img.shape[0]
width = img.shape[1]
channels = img.shape[2]
Read more about this here:

opencv-python image processing code-debugging

I have written a code in OCV-python for image processing(detection of veins in eye), its not working, can somebody help?
import os,sys
import numpy as np
import scipy
import cv2
import PIL
import Image
import ImageChops
i=cv2.imread('eye.jpg',0);
cv2.imshow(i);
j= cv2.medianBlur(i, 3);
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8));
k= clahe.apply(j);
kernel = np.ones((5,5),np.uint8);
closing = cv2.morphologyEx(k, cv2.MORPH_CLOSE, kernel);
h, w = i.shape[:2];
seed_pt = None;
mask = np.zeros((h+2, w+2), np.uint8);
l=cv2.floodFill(k, mask, seed_pt, (255, 255, 255));
o=ImageChops.difference(closing,l);
(thresh, im_bw) = cv2.threshold(o, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU);
cv2.imshow(im_bw);
'
particularly having problem with reading a .jpg file(it reads a .png file), the imshow() function is not working, and errors are being shown for the imagechops and otsu threshold function.
the matlab code for the above code is(it is working perfectly):
t=('http://www.ohiolionseyeresearch.com/core/files/uploads/2014/03/1217.png');
i=imread(t);
figure, imshow(i)
q=rgb2hsv(i);
t=rgb2gray(i);
figure, imshow(t)
k=medfilt2(t);
figure, imshow(k)
u=adapthisteq(k);
se=strel('disk',10);
c=imclose(u,se);
figure, imshow(c)
d=imfill(u,'holes');
figure, imshow(d)
z=imabsdiff(c,d);
figure, imshow(z)
level=graythresh(z);
BW=im2bw(z,level);
imshow(BW)
'

Categories

Resources