Issue
I want to extract each sticker 5x6 and to total 30 sticker
like below , how do I do so
(expect pic ) https://i.stack.imgur.com/rIzPg.jpg
(original picture) https://i.stack.imgur.com/ng7oV.jpg
from below link I come up my code
How extract pictures from an big image in python
- following the suggestion:
The black pixels along the top are a distraction, so are the black pixels of the QR codes. You are only interested in the white stickers.
So, take a copy of your image and threshold at a high value to give you pure white stickers surrounded by black and with black QR codes within each sticker. Now find white contours and reject black ones.
Apply the contours found on the thresholded image to your original image.
I'm doing the Thresholding expecting pure white stickers surrounded by black and with black QR codes within each sticker
import numpy as np
import glob
import matplotlib.pyplot as plt
import skimage.io
import skimage.color
import skimage.filters
from PIL import Image
import pytesseract
import cv2 as cv
import numpy as np
def custom_blur_demo(image):
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) #锐化
dst = cv.filter2D(image, -1, kernel=kernel)
cv.imwrite("/home/joy/桌面/test_11_4/sharpen_images.png", dst)
cv.imshow("custom_blur_demo", dst)
src = cv.imread("/home/joy/桌面/test_11_4/original.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
custom_blur_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
# load the image
image = skimage.io.imread("/home/joy/桌面/test_11_4/sharpen_images.png")[:,:,:3]
# image = imageio.imread(image_name)[:,:,:3]
# img = rgb2gray(image)
fig, ax = plt.subplots()
plt.imshow(image)
# convert the image to grayscale
gray_image = skimage.color.rgb2gray(image)
# blur the image to denoise
blurred_image = skimage.filters.gaussian(gray_image, sigma=1.0)
fig, ax = plt.subplots()
plt.imshow(blurred_image, cmap="gray")
# create a histogram of the blurred grayscale image
histogram, bin_edges = np.histogram(blurred_image, bins=256, range=(0.0, 1.0))
fig, ax = plt.subplots()
plt.plot(bin_edges[0:-1], histogram)
plt.title("Grayscale Histogram")
plt.xlabel("grayscale value")
plt.ylabel("pixels")
plt.xlim(0, 1.0)
# create a mask based on the threshold
t1 = 0.72
t2 = 0.05
binary_mask = blurred_image < t1
fig, ax = plt.subplots()
plt.imshow(binary_mask, cmap="gray")
aaa = plt.imshow(binary_mask, cmap="gray")
plt.show()
plt.savefig("/home/joy/桌面/test_11_4/sharpen_images_del_gray_part.png", aaa)
img = Image.open('/home/joy/桌面/test_11_4/sharpen_images_del_gray_part.png')
text = pytesseract.image_to_string(img, lang='eng')
print("file name" ,"final output", ".png")
print("size")
print(img.size)
print(text)
here is the output for mine Thresholding : https://i.stack.imgur.com/ng7oV.jpg
the product does after Thresholding but the word on every sticker seems blur (I'm going to OCR image to text every single sticker img later)
- not correct yet, I want sticker part only that without gray color part
(pic 5b) in same link is how I reach for now https://i.stack.imgur.com/ng7oV.jpg
How to cut them in small piece, the sticker size
(expect pic ) https://i.stack.imgur.com/rIzPg.jpg
Solution
This effort is probably not scientifically generalizable. Just wanted to show it doesn't need Contour-finding/Binarization. just pixel value comparison might be enough.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
orig_image = cv.imread("sample.png")
gray = cv.cvtColor(orig_image, cv.COLOR_BGR2GRAY)
kernel = np.ones((3,3),np.uint8)
eroded = cv.erode(gray,kernel,iterations = 1)
def show_img(img_bgr):
fig, ax = plt.subplots(figsize=(5, 5))
rgb = cv.cvtColor(img_bgr, cv.COLOR_BGR2RGB)
ax.imshow(rgb)
return fig
def detect_top_bottom(original_img, erodded_img):
"""Detects only top and bottom row number of each row of Qr_Codes.
"""
line_img = original_img.copy()
height, width = erodded_img.shape
top = 0
top_drawn = False
rows_range = []
for row in range(erodded_img.shape[0]):
for col in range(erodded_img.shape[1]):
if np.mean(erodded_img[row,col]) > 190:
if row - top > 3 and not top_drawn:
cv.line(line_img, (0, row), (width, row), (0,255,0), 2)
rows_range.append([row,None])
top_drawn = True
top = row
break
else:
if top_drawn:
cv.line(line_img, (0, row), (width, row), (0,255,0), 2)
rows_range[-1][1] = row
top_drawn = False
return line_img, rows_range
# make original image grayscale
gray = cv.cvtColor(orig_image, cv.COLOR_BGR2GRAY)
# erode image with 3x3 kernel in order to remove small noises
kernel = np.ones((3,3),np.uint8)
eroded = cv.erode(gray,kernel,iterations = 1)
line_img, rows_range = detect_top_bottom(orig_image, eroded)
# Rotate image 90 degs clockwise in order to use same function for detection
eroded_rotated_90 = cv.rotate(eroded, cv.ROTATE_90_CLOCKWISE)
line_img_rotated_90 = cv.rotate(line_img, cv.ROTATE_90_CLOCKWISE)
line_img, cols_range = detect_top_bottom(line_img_rotated_90, eroded_rotated_90)
# finally rotate 90 deg counter clockwise in to get orignal.
line_img= cv.rotate(line_img, cv.ROTATE_90_COUNTERCLOCKWISE)
fig = show_img(line_img)
fig.savefig("original_grid.png")
fig, axs = plt.subplots(len(rows_range), len(cols_range))
for i, row in enumerate(rows_range):
for j, col in enumerate(cols_range):
axs[i,j].axis('off')
# just for sake of visualization conver to RGB
# axs[i,j].imshow(orig_image[row[0]:row[1], :][:,col[0]:col[1]]) probabely is enough
orig_sub_channels = cv.cvtColor(orig_image[row[0]:row[1], :][:,col[0]:col[1]], cv.COLOR_BGR2RGB)
axs[i,j].imshow(orig_sub_channels)
fig.savefig("splitted_grid.png")
Answered By - M.Armoun
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.