I have displayed the code below, but when I try to execute it, get
Traceback (most recent call last):
File "/home/decentmakeover2/Code/cv.py", line 22, in <module>
img = cv2.circle(img,center, radius, (0,255, 0), 2)
TypeError: integer argument expected, got float
Im not exactly sure what the problem is, in the minEnclosingCircle the values have been converted to int, but i still get the same error, any ideas on what might be the problem?
import numpy as np
import cv2
import os
from scipy import ndimage
img = cv2.pyrDown(cv2.imread('img.jpeg'))
ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)
image, contours, heir = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
x, y , w, h = cv2.boundingRect(c)
cv2.rectangle(img, (x,y), (x+w, y+h), (0, 255, 0), 2)
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], 0 , (0, 0, 255), 3)
(x,y), radius = cv2.minEnclosingCircle(c)
center = (int(x), int(y))
radius = int(radius)
img = cv2.circle(img, center, radius, (0,255, 0), 2)
cv2.drawContours(img, contours, -1, (255, 0, 0), 1)
cv2.imshow('contours',img)
cv2.waitKey(0)
cv2.destroyAllWindows()`
This answer is probably too late, but I found that cv2.circle only can accept centre coordinates precision up to float32. If the coordinates are in float64, it will throw this error. Simple solution is always converting centre coordinates to numpy.float32.
I have done small changes to your code for conversion of float numbers to integers. It is running without errors now. Check this:
import numpy as np
import cv2
import os
from scipy import ndimage
img = cv2.pyrDown(cv2.imread('img.jpeg'))
ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)
image, contours, heir = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
x, y ,w ,h = cv2.boundingRect(c)
cv2.rectangle(img, (x,y), (x+w, y+h), (0, 255, 0), 2)
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], 0 , (0, 0, 255), 3)
(x,y), radius = cv2.minEnclosingCircle(c)
x = np.round(x).astype("int")
y = np.round(y).astype("int")
center = (x,y)
radius = np.round(radius).astype("int")
cv2.circle(img, center, radius, (0,255, 0), 2)
cv2.drawContours(img, contours, -1, (255, 0, 0), 1)
cv2.imshow('contours',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Modify your code as follows you do not need to use return value of cv2.circle.
cv2.circle(img,center, radius, (0,255, 0), 2)
Related
The tesseract/pytesseract don't display the japanese characters in the final image but it display in the run tab in Pycharm.
Source image:
japp.jpg
Here's the final image output:
final image ouput
Here's the display on the run tab in Pycharm:
enter image description here
I'm expecting to see that the japanese characters will display on the final image. Help me please I've been fixing it for almost 4 hours now. How can I achieve this?
Here is my code:
import cv2
from pytesseract import pytesseract
from pytesseract import Output
import numpy as np
pytesseract.tesseract_cmd = "C:\\Program Files\\Tesseract-OCR\\tesseract.exe"
img = cv2.imread('japp.jpg')
img = cv2.resize(img, (600, 360))
print(pytesseract.image_to_string(img, lang='jpn+eng'))
hImg, wImg, _ = img.shape
norm_img = np.zeros((img.shape[0], img.shape[1]))
norm = cv2.normalize(img, norm_img, 0, 255, cv2.NORM_MINMAX)
thresh = cv2.threshold(norm, 100, 255, cv2.THRESH_BINARY)[1]
img = cv2.GaussianBlur(thresh, (1, 1), 0)
cv2.imshow('normalize', norm)
cv2.imshow('threshold', thresh)
data4 = pytesseract.image_to_data(img, lang='jpn+eng')
for z, a in enumerate(data4.splitlines()):
if z != 0:
a = a.split()
if len(a) == 12:
x, y = int(a[6]), int(a[7])
w, h = int(a[8]), int(a[9])
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1)
cv2.putText(img, a[11], (x, y - 2), cv2.FONT_HERSHEY_DUPLEX, 0.5, (0, 0, 255), 1)
cv2.imshow('final image', img)
cv2.waitKey(0)
I have two connected rectangles with a diamond in between them. In Entity Relationship Diagram (ERD) we have the same scenario. My aim is to detect both the rectangles and the diamond which is in between them.
import cv2
import numpy as np
from matplotlib import pyplot as plt
# reading image
img = cv2.imread('pic4.jpeg')
# converting image into grayscale image
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# setting threshold of gray image
_, threshold = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# using a findContours() function
contours, _ = cv2.findContours(
threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
i = 0
# list for storing names of shapes
for contour in contours:
# here we are ignoring first counter because
# findcontour function detects whole image as shape
if i == 0:
i = 1
continue
# cv2.approxPloyDP() function to approximate the shape
approx = cv2.approxPolyDP(
contour, 0.01 * cv2.arcLength(contour, True), True)
# using drawContours() function
cv2.drawContours(img, [contour], 0, (0, 0, 0), 5)
# finding center point of shape
M = cv2.moments(contour)
if M['m00'] != 0.0:
x = int(M['m10']/M['m00'])
y = int(M['m01']/M['m00'])
# putting shape name at center of each shape
if len(approx) == 3:
cv2.putText(img, 'Triangle', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
elif len(approx) == 4:
cv2.putText(img, 'Rectangle', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
elif len(approx) == 5:
cv2.putText(img, 'Pentagon', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
elif len(approx) == 6:
cv2.putText(img, 'Hexagon', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
else:
cv2.putText(img, 'circle', (x, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
# displaying the image after drawing contours
cv2.imshow('pic4', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Input image
Output image after shapes detection
The output image is not detecting correct shape. It must have to write a rectangle once in both rectangle shapes.
I am working on an OCR project using OpenCV & Tesseract. I have successfully identified the shape of the receipt and now I am trying to extract the angle of the shape (drawn with green below) to deskew the image.
To detect the contour I used more RETR_EXTERNAL method, as I found it produces the best results for my dataset (the contours of background noise is minimal)
code to extract all contours
image2 = cv2.imread('./Dataset - Receipt Images/1036-receipt.jpg')
img_gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)
ret, thresh2 = cv2.threshold(img_gray2, 150, 255, cv2.THRESH_BINARY)
contours4, hierarchy4 = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
image_copy5 = image2.copy()
cv2.drawContours(image_copy5, contours4, -1, (0, 255, 0), 2, cv2.LINE_AA)
cv2.imshow('EXTERNAL', image_copy5)
To get the largest contour (blue box) I applied the following:
def drawMaxAreaContour(contours, image):
if len(contours) != 0:
c = max(contours, key=cv2.contourArea)
cv2.drawContours(image, c, 1, (0, 0, 255), 5)
x, y, w, h = cv2.boundingRect(c)
cv2.rectangle(image, (x, y), (x + w, y + h), (250, 0, 0), 2)
To get the angle of the shape, i tried:
cv2.minAreaRect(c)
And the results is 0 - the angle of the green box is 0, which is obviously not true.
So, specifically, my question:
2. OR how can I get the angle of that shape? (assuming it would be applied on the shape of a receipt, not a rectangular shape, like the blue one in my case)
Processed picture
I am new to OpenCV. I have two questions to ask.
I am trying to print the no of contours available after applying the area. I am getting the correct output in imshow but not in the print statement. I understood that print(len(contours)) gives the total number of contours but I need the no of contours in the given area > 400. You can check the below python code for more details. Please help me with this.
Is it possible to change the threshold value above 255, whenever I change it to above 255, I am getting the black image even if I increase the max value?
Thank you!
import cv2 as cv
import numpy as np
im_color = cv.imread("D:\python_project\Focus_detection_1/_00005_cells.png", cv.IMREAD_COLOR)
im_gray = cv.cvtColor(im_color, cv.COLOR_BGR2GRAY)
_, thresh = cv.threshold(im_gray, thresh=254, maxval=255, type=cv.THRESH_BINARY)
mask = cv.cvtColor(thresh, cv.COLOR_GRAY2BGR)
im_thresh_color = cv.bitwise_and(im_color,mask)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
cv.drawContours(im_thresh_color,contours,-1,(0,0,255),2)
for c in contours:
area = cv.contourArea(c)
if area > 400:
x,y,w,h = cv.boundingRect(c)
im = cv.rectangle(im_thresh_color, (x,y), (x+w, y+h), (255,0,0), 2)
cv.drawContours(im_thresh_color,contours, -1,(0,0,255),2) #-1 is to draw all the contour, 0 is the 1st contour and so on
text = cv.putText(im, 'Focused', (x, y), cv.FONT_HERSHEY_SIMPLEX, 0.5, (36, 255, 12), 2)
no_of_images = len(contours)
print("images:", no_of_images)
while True:
cv.imshow("original image", im_color)
cv.imshow("Thresh color with contour", im_thresh_color)
#print("n:",len(im_thresh_color))
if cv.waitKey(1) == ord("n"):
break
cv.destroyAllWindows()
Here is the updated code for your first question: This code counts how many contours are in the area and then prints the number of contours in that area
import cv2 as cv
import numpy as np
im_color = cv.imread("D:\python_project\Focus_detection_1/_00005_cells.png", cv.IMREAD_COLOR)
im_gray = cv.cvtColor(im_color, cv.COLOR_BGR2GRAY)
_, thresh = cv.threshold(im_gray, thresh=254, maxval=255, type=cv.THRESH_BINARY)
mask = cv.cvtColor(thresh, cv.COLOR_GRAY2BGR)
im_thresh_color = cv.bitwise_and(im_color, mask)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
cv.drawContours(im_thresh_color, contours, -1, (0, 0, 255), 2)
counter = 0
for c in contours:
area = cv.contourArea(c)
if area > 400:
x, y, w, h = cv.boundingRect(c)
im = cv.rectangle(im_thresh_color, (x, y), (x+w, y+h), (255, 0, 0), 2)
# -1 is to draw all the contour, 0 is the 1st contour and so on
cv.drawContours(im_thresh_color, contours, -1, (0, 0, 255), 2)
text = cv.putText(im, 'Focused', (x, y), cv.FONT_HERSHEY_SIMPLEX, 0.5, (36, 255, 12), 2)
counter += 1
print("images:", counter)
while True:
cv.imshow("original image", im_color)
cv.imshow("Thresh color with contour", im_thresh_color)
# print("n:",len(im_thresh_color))
if cv.waitKey(1) == ord("n"):
break
cv.destroyAllWindows()
Answer question 2: no it is not possible to change it over a value of 255 bc the range of the r,g,b values is from 0 to 255.
i have the image shown below and i am attempting to just capture the Squares and place a green line around them any help or direction would be great.
import numpy as np
import cv2
img = cv2.imread('beef.png')
imgGry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret , thrash = cv2.threshold(imgGry, 240 , 255, cv2.CHAIN_APPROX_NONE)
contours , hierarchy = cv2.findContours(thrash, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
for contour in contours:
approx = cv2.approxPolyDP(contour, 0.01* cv2.arcLength(contour, True), True)
cv2.drawContours(img, [approx], 0, (0, 0, 0), 5)
x = approx.ravel()[0]
y = approx.ravel()[1] - 5
x, y , w, h = cv2.boundingRect(approx)
aspectRatio = float(w)/h
print(aspectRatio)
if aspectRatio >= 0.95 and aspectRatio < 1.05:
cv2.putText(img, "square", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
else:
cv2.putText(img, "rectangle", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
cv2.imshow('shapes', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
I don't know exactly what your problem is (are the contours wrong? Nothing is being drawn on the image? etc) but here are some guesses.
To draw lines around the contours, it looks like you are currently using white (0,0,0) to outline it. -1 is to draw all contours to see if you are getting any results.
Also some cv2 functions are destructive so I never use img when I am creating the output image. I would imShow and drawContours on a copy of the original img.
cv2.drawContours(img, contours, -1, GREEN, 5)