I am trying to detect a black tape on a black background.
No tape, with tape (cropped pictures):
I have first cropped the area of the tape from the original image and then performing thresholding on it. Below is the image when there is no tape:
You can notice there is an almost solid line. Black tape is placed right next to it and when it is placed this line becomes very light. Below is the image:
Is there any good image processing techniques I can use to detect when the black tape is placed and when its not placed?
Below is the code I am currently using:
import cv2
import os
import imutils
from pathlib import Path
import numpy as np
def on_mouse(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
print("X: {} | Y: {}".format(x, y))
dirPath = Path(__file__).parents[2]
imgPath = os.path.join(dirPath, "img", "img.png")
win_name = "Image"
cv2.namedWindow(win_name)
cv2.setMouseCallback(win_name, on_mouse)
img = cv2.imread(imgPath)
img = imutils.resize(img, width=800)
roiImg = img[298:337, 520:591]
img_gray = cv2.cvtColor(roiImg, cv2.COLOR_BGR2GRAY)
rett, thresh = cv2.threshold(img_gray, 50, 255, cv2.THRESH_BINARY)
cv2.imshow(win_name, img)
cv2.imshow("Thres", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
Here is the link to test video: https://drive.google.com/file/d/1P3Xkx_SuHidDs1UdacS3-DZqA-CiXQOX/view?usp=sharing
Below is the image with area marked in red where tape is usually placed
Thanks
No way to write a stable image processing software here.
In this industrial environment you get differences in ambient light, reflexion, shadows, light different presentation angles, sun light etc. This will impact the brightness of your image partial or global much more than the presence of a nearly invisible tape. This way it's not possible to find any good threshold.
So I guess you are on the right way using the "temporary solution" of detecting the gray hand.
If you really like to detect the tape you need a hardware solution that brings you away from this black on black thing:
Use white tape on black part or black tape on white part. Only to mention :-)
Use dark/bright field illumination instead of ambient light. Guess will not work because angle of part and tape is similar.
Use different wavelength with more difference than in visible light. Needs specific camera and illumination. Best wavelength depends a lot of the material but that's the most professional and stable solution here.
Related
I have a problem here during cropping and saving image by using opencv.
I'm trying to crop by using cv2.SelectROI function but after I drag on the image, cv.2imshow won't work properly.
Here's my code:
import cv2, numpy as np
img = cv2.imread('C:/git/ML/Image/colorful.jpg')
x,y,w,h = cv2.selectROI('img', img, False)
if w and h:
roi = img[y:y+h, x:x+w]
cv2.imshow('cropped', roi)
cv2.moveWindow('cropped', 0, 0)
cv2.imwrite('cropped2.jpg',roi)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
print(x,y,w,h)
I've tried to change directory in various ways, put imshow method just before selectROI but none of them worked so far.
cv2.imshow itself shouldn't be a problem because when I don't use selectROI and just manually code the cropping performance from start to finish(by defining mouseleftbutton click, drag, leftbuttonup one by one), cv2.imshow, cv2.movewindow and cv2.imwrite works just fine.
also, not confident that the code itself have interal problem because in other computer, those activities(dragging, cropping, open in new window, save) seems to be working just fine.
is there a possibility that i haven't installed sth that should be needed in order to run selectROI..?
Anyways.. any comments will be much appreciated. Plz help me.
I am trying to do face detection but it does not detect any face.
this is the function I have created for face detection
def faceDetection(test_img):
gray_img=cv2.cvtColor(test_img,cv2.COLOR_BGR2GRAY)
face_haar_cascade=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# haar classifier
faces=face_haar_cascade.detectMultiScale(gray_img,scaleFactor=1.32,minNeighbors=5)
return faces,gray_img
this is used in
test_img=cv2.imread('pic.png')
faces_detected,gray_img=fr.faceDetection(test_img)
print("faces_detected:",faces_detected)
for (x,y,w,h) in faces_detected:
cv2.rectangle(test_img,(x,y),(x+w,y+h),(255,0,0),thickness=5)
resized_img=cv2.resize(test_img,(500,500))
cv2.imshow("face",resized_img)
cv2.waitKey(0)
cv2.destroyAllWindows
but when I run this script it does not show any face detected
simply give output this
faces_detected: ()
and no box around image
Try using a different haar cascade. The default one is haarcascade_frontalface_alt.xml
face_haar_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
Change the scale factor you use for the cascade. If that doesn't work you can also reduce also the number of neighbors to maybe 2.
faces = face_haar_cascade.detectMultiScale(gray_img, scaleFactor=1.1, minNeighbors=5);
Check the number of faces you found
print('Faces found: ', len(faces))
I'm currently making a game in pygame, Python 3 and a part of the code that has been giving me issues is:
for counter in range(0, 30):
particles = pygame.image.load('particles.png').convert()
particles = pygame.transform.rotozoom(particles, 36*counter, 1.1**counter).convert()
particles.set_colorkey((0, 0, 0, 0))
screen.blit(particles, particles.get_rect(centerx=480, centery=100))
pygame.display.flip()
time.sleep(0.05)
particles.png is just a few colored pixels on a transparent background. The problem is that when the image is rotated and scaled, some of those particles sort of blur out resulting in a mass of black squares around them.
How do I fix this problem? Thanks in advance!!
I've had a bad experience with pygame's rotozoom combined with transparency. Instead of loading the image and then rotozooming it, consider the following:
Using PIL library:
Convert the loaded surface to a string using pygame.image.tostring
Convert the string to an Image object
Use PIL's functions to replace rotozoom (zooming, rotating)
Convert the Image object back into a surface using the same method
Using math:
Load data about the position and color of the particles,
or infer it from the loaded surface
Use simple mathematical functions to caculate their new position,
according to the angle and zoom
Paint them using pygame.gfxdraw, pygame.draw or pygame.Surface.set_at
Good luck!
I've showed in various ways how to take images with a webcam in Python (see How can I take camera images with Python?). You can see that the images taken with Python are considerably darker than images taken with JavaScript. What is wrong?
Image example
The image on the left was taken with http://martin-thoma.com/html5/webcam/, the one on the right with the following Python code. Both were taken with the same (controlled) lightning situation (it was dark outside and I only had some electrical lights on) and the same webcam.
Code example
import cv2
camera_port = 0
camera = cv2.VideoCapture(camera_port)
return_value, image = camera.read()
cv2.imwrite("opencv.png", image)
del(camera) # so that others can use the camera as soon as possible
Question
Why is the image taken with Python image considerably darker than the one taken with JavaScript and how do I fix it?
(Getting a similar image quality; simply making it brighter will probably not fix it.)
Note to the "how do I fix it": It does not need to be opencv. If you know a possibility to take webcam images with Python with another package (or without a package) that is also ok.
Faced the same problem. I tried this and it works.
import cv2
camera_port = 0
ramp_frames = 30
camera = cv2.VideoCapture(camera_port)
def get_image():
retval, im = camera.read()
return im
for i in xrange(ramp_frames):
temp = camera.read()
camera_capture = get_image()
filename = "image.jpg"
cv2.imwrite(filename,camera_capture)
del(camera)
I think it's about adjusting the camera to light. The former
former and later images
I think that you have to wait for the camera to be ready.
This code works for me:
from SimpleCV import Camera
import time
cam = Camera()
time.sleep(3)
img = cam.getImage()
img.save("simplecv.png")
I took the idea from this answer and this is the most convincing explanation I found:
The first few frames are dark on some devices because it's the first
frame after initializing the camera and it may be required to pull a
few frames so that the camera has time to adjust brightness
automatically.
reference
So IMHO in order to be sure about the quality of the image, regardless of the programming language, at the startup of a camera device is necessary to wait a few seconds and/or discard a few frames before taking an image.
Tidying up Keerthana's answer results in my code looking like this
import cv2
import time
def main():
capture = capture_write()
def capture_write(filename="image.jpeg", port=0, ramp_frames=30, x=1280, y=720):
camera = cv2.VideoCapture(port)
# Set Resolution
camera.set(3, x)
camera.set(4, y)
# Adjust camera lighting
for i in range(ramp_frames):
temp = camera.read()
retval, im = camera.read()
cv2.imwrite(filename,im)
del(camera)
return True
if __name__ == '__main__':
main()
So, I'm generating a binary (well, really gray scale, 8bit, used as binary) image with python and opencv2, writing a small number of polygons to the image, and then dilating the image using a kernel. However, my source and destination image always end up the same, no matter what kernel I use. Any thoughts?
from matplotlib import pyplot
import numpy as np
import cv2
binary_image = np.zeros(image.shape,dtype='int8')
for rect in list_of_rectangles:
cv2.fillConvexPoly(binary_image, np.array(rect), 255)
kernel = np.ones((11,11),'int')
dilated = cv2.dilate(binary_image,kernel)
if np.array_equal(dilated, binary_image):
print("EPIC FAIL!!")
else:
print("eureka!!")
All I get is EPIC FAIL!
Thanks!
So, it turns out the problem was in the creation of both the kernel and the image. I believe that openCV expects 'uint8' as a data type for both the kernel and the image. In this particular case, I created the kernel with dtype='int', which defaults to 'int64'. Additionally, I created the image as 'int8', not 'uint8'. Somehow this did not trigger an exception, but caused the dilation to fail in a surprising fashion.
Changing the above two lines to
binary_image = np.zeros(image.shape,dtype='uint8')
kernel = np.ones((11,11),'uint8')
Fixed the problem, and now I get EUREKA! Hooray!