What would you recommend me in order to get a better fingerprints extraction? I doesn't look so well. Thank you. Here's my code:
import cv2
import numpy as np
img = cv2.imread("huella.jpg")
img = cv2.resize(img, None, fx=0.7, fy=1.0, interpolation=cv2.INTER_AREA)
w, h = img.shape[:2]
fp = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sharp = np.array([[-1, -1, -1, -1, -1], [-1, 2, 2, 2, -1], [-1, 2, 8, 2, -1], [-1, 2, 2, 2, -1], [-1, -1, -1, -1, -1]]) / 8
fp = cv2.filter2D(fp, -1, sharp)
fp = cv2.Canny(fp, 45, 45)
cv2.imshow("Original", img)
cv2.imshow("Huella", fp)
cv2.waitKey(0)
cv2.destroyAllWindows()
Images
You need to use morphological operation.
First. Try to use cv2.dilate() and then cv2.erode(). This should remove all small and far object.
You can see full documentation here.
Morphological Transformations
Eroding and Dilating
New Edit:
The image will lost the information upon dilate and erode, so here is a script to remove small connected component. You should change the minSize as your need.
import cv2
import numpy as np
def remove_small_pixel(img, minSize=50):
nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(img, None, None, None, 8, cv2.CV_32S)
sizes = stats[1:, -1] # get CC_STAT_AREA component
img2 = np.zeros(labels.shape, np.uint8)
for i in range(0, nlabels - 1):
if sizes[i] >= minSize: # filter small dotted regions
img2[labels == i + 1] = 255
return img2
Note: This script only available for grayscale image.
Related
im trying to make the template image black except for the red rectangle which has BGR [0, 4, 95]. below code works for other colored rectangles but i figured it wont work sometimes with specific BGR. (in this case, it wont work with [0, 4, 95]) i have no idea why it wont.
can anyone tell me what im missing?
import numpy as np
import cv2
output_color = [0,4,95]
img = cv2.imread('1.png', cv2.IMREAD_UNCHANGED)
img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
img = np.where(np.all(img == output_color, axis=2, keepdims=True), output_color, [0, 0, 0])
img = img[..., 0].astype('uint8')
cv2.imshow("output", img)
cv2.waitKey()
cv2.destroyAllWindows()
result i get
result i want
Original Image
Expected Output.
I am using this code for translating a specific part into the same image, but output is not changing,
import numpy as np
import cv2 as cv
img = cv.imread('eye0.jpg', 0)
rows, cols = img.shape
roi = img[200: 300, 360: 450]
M = np.float32([[1, 0, 100], [0, 1, 50]])
dst = cv.warpAffine(roi, M, roi.shape)
cv.imshow('img', img)
cv.imshow('img', dst)
cv.waitKey(0)
cv.destroyAllWindows()
I see no changes from original image. How can I do so? Moreover, as an openCV newbie I would like to know which function should I use/explore here to get my purpose served?
Copy() function can help you instead of warpAffine(). You can check here also:
Here is output and code:
import numpy as np
import cv2 as cv
img = cv.imread('eye.jpg', 1)
#rows, cols = img.shape
roi = img[80: 100, 140: 160]
img2 = img.copy()
img2[95:115, 140:160]=roi
cv.imshow('img', img)
cv.imshow('imaag', img2)
cv.waitKey(0)
cv.destroyAllWindows()
**Image after warp affine tranformation... but for circling the part it seem difficult..
**
import numpy as np
import cv2 as cv
img = cv.imread('eye.jpg')
roi = img[78: 100, 130: 160]
M = np.float32([[1, 0, 6], [0, 1, 4]])
dst = cv.warpAffine(roi, M, (30, 22))
img[80:102, 132:162] = dst
cv.imwrite("newimage.jpg",img)
cv.imshow('img', img)
cv.imshow('img1',dst)
cv.waitKey(0)
cv.destroyAllWindows()
Im working on a school project, where I need create a semantic map from the camera picture. The picture is of an agricultural land. The goal is to create it without the help of CNN or learning methods, just classical methods of detection.
I searched for similar methods and algorithm and this is my code and the result, but the algorithm is not good detecting the edges of the various fields in the image.
from __future__ import print_function
import cv2 as cv
import numpy as np
import imutils
import argparse
import random as rng
rng.seed(12345)
src = cv.imread('field.jpg')
src = imutils.resize(src, width=600)
# Show source image
cv.imshow('Source Image', src)
src[np.all(src == 255, axis=2)] = 0
# Show output image
cv.imshow('Black Background Image', src)
kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]], dtype=np.float32)
# do the laplacian filtering as it is
# well, we need to convert everything in something more deeper then CV_8U
# because the kernel has some negative values,
# and we can expect in general to have a Laplacian image with negative values
# BUT a 8bits unsigned int (the one we are working with) can contain values from 0 to 255
# so the possible negative number will be truncated
imgLaplacian = cv.filter2D(src, cv.CV_32F, kernel)
sharp = np.float32(src)
imgResult = sharp - imgLaplacian
# convert back to 8bits gray scale
imgResult = np.clip(imgResult, 0, 255)
imgResult = imgResult.astype('uint8')
imgLaplacian = np.clip(imgLaplacian, 0, 255)
imgLaplacian = np.uint8(imgLaplacian)
#cv.imshow('Laplace Filtered Image', imgLaplacian)
cv.imshow('New Sharped Image', imgResult)
bw = cv.cvtColor(imgResult, cv.COLOR_BGR2GRAY)
_, bw = cv.threshold(bw, 125, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow('Binary Image', bw)
dist = cv.distanceTransform(bw, cv.DIST_L2, 3)
# Normalize the distance image for range = {0.0, 1.0}
# so we can visualize and threshold it
cv.normalize(dist, dist, 0, 1.0, cv.NORM_MINMAX)
cv.imshow('Distance Transform Image', dist)
_, dist = cv.threshold(dist, 0.4, 1.0, cv.THRESH_BINARY)
# Dilate a bit the dist image
kernel1 = np.ones((3,3), dtype=np.uint8)
dist = cv.dilate(dist, kernel1)
cv.imshow('Peaks', dist)
dist_8u = dist.astype('uint8')
# Find total markers
_, contours, _ = cv.findContours(dist_8u, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# Create the marker image for the watershed algorithm
markers = np.zeros(dist.shape, dtype=np.int32)
# Draw the foreground markers
for i in range(len(contours)):
cv.drawContours(markers, contours, i, (i+1), -1)
# Draw the background marker
cv.circle(markers, (5,5), 3, (255,255,255), -1)
cv.imshow('Markers', markers*10000)
cv.watershed(imgResult, markers)
#mark = np.zeros(markers.shape, dtype=np.uint8)
mark = markers.astype('uint8')
mark = cv.bitwise_not(mark)
# uncomment this if you want to see how the mark
# image looks like at that point
#cv.imshow('Markers_v2', mark)
# Generate random colors
colors = []
for contour in contours:
colors.append((rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)))
# Create the result image
dst = np.zeros((markers.shape[0], markers.shape[1], 3), dtype=np.uint8)
# Fill labeled objects with random colors
for i in range(markers.shape[0]):
for j in range(markers.shape[1]):
index = markers[i,j]
if index > 0 and index <= len(contours):
dst[i,j,:] = colors[index-1]
# Visualize the final image
cv.imshow('Final Result', dst)
cv.waitKey()
``
[1]: https://i.stack.imgur.com/qpE4s.jpg
I want to detect lines in an image which is at 45 degrees only with respect to the origin. I have to do it with 3x3 convolution only. I have solved it such that all lines at 45 degrees are removed and everything else stays(inverse of what I want). Any help in reaching from here to my final goal will be highly appreciated, thanks.
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('Lines.png')
plt.imshow(img, cmap='gray')
plt.show()
kernel = np.array([[0, -1, 0],
[1, 0, 1],
[0, -1, 0]])
dst = cv2.filter2D(img, -1, kernel)
cv2.imwrite("filtered.png", dst)
This is the image before convolution:
This is the image after convolution:
Well by the code you have provided in the question we obtained lines except those which we want to obtain. So we can take that and dilate it to fill the lines.
img = cv2.imread('lines.png')
kernel = np.array([[0, -1, 0],
[1, 0, 1],
[0, -1, 0]])
dst = cv2.filter2D(img, -1, kernel)
kernel = np.ones((5, 5), np.uint8)
dilated = cv2.dilate(dst, kernel, iterations = 1)
Then we need to remove the dots above the lines at 45 degrees so we use morphological opening for that and threshold the image to convert all the lines to pixel values=255.
kernel = np.ones((7, 7), np.uint8)
opening = cv2.morphologyEx(dilated, cv2.MORPH_OPEN, kernel)
_,thresh = cv2.threshold(opening,10,255,cv2.THRESH_BINARY)
Then using cv2.bitwise_and of original image and cv2.bitwise_not of the threshold obtained we obtain our lines.
res = cv2.bitwise_and(img, cv2.bitwise_not(thresh))
We obtain the lines but we need to remove the circle in the middle. For that we use cv2.erode on the original image to obtain only the middle circle, threshold it and then again use cv2.bitwise_and and cv2.bitwise_not to remove it from res.
kernel = np.ones((7, 7), np.uint8)
other = cv2.erode(img, kernel, iterations = 1)
_,thresh = cv2.threshold(other,10,255,cv2.THRESH_BINARY)
result = cv2.bitwise_and(res, cv2.bitwise_not(thresh))
cv2.imshow("Image", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
The filter I used is:
kernel = np.array([[0, -25, 1],
[-25, 5, -25],
[1, -25, 0]])
and the result was:
It wasn't perfect, but hope it helps.
I have a 2d numpy array that has 0's where there is not an object, and 1's where there is an object.
matrix.shape = (500, 425)
I want to create a numpy array mask of shape (500, 425, 3) such that:
mask = np.zeros((500, 425, 3))
if matrix[x][y] == 0:
mask[x][y] = np.array([0, 0, 0]) # Black pixel if no object
else:
mask[x][y] = np.array([0, 255, 0]) # Green pixel if object
So that I have green pixels where the object are, black pixels everywhere else. How do I create this mask? Will this work correctly, such that if I use cv2.addWeighted to the image and the mask, the object will have a transparent green mask over it?
You're describing an "over" or "blend" image compositing operation. You can combine the images directly using your mask image.The general formula for combining two images in this way is:
A*alpha + B*(1-alpha)
Where A is the image being placed on top of image B. Alpha can be any value between black and white. Gray alpha values will make A appear transparent. It is usually easier to convert to a float image because the math is much easier when the values are between 0 and 1.
If you have image A (your source image) and image B (a green image) and your mask (matrix). You can overlay image B on top of image A using:
outimg[x][y] = (B[x][y] * matrix[x][y]) + (A[x][y] * (1-matrix[x][y]))
or if you want transparency:
#50% transparency
t = 0.5
outimg[x][y] = (B[x][y] * (matrix[x][y]*t)) + (A[x][y] * (1-(matrix[x][y]*t)))
If you want to put image A on top of image B you can just reverse the terms in the expression.
Here is an example of compositing image A (a flat green image) on top of image B (the source image) with a mask and transparency:
source image:
mask image:
import numpy as np
import cv2
i = cv2.imread('lena.bmp')
#convert to floating point
img = np.array(i, dtype=np.float)
img /= 255.0
cv2.imshow('img',img)
cv2.waitKey(0)
j = cv2.imread('lena_mask.bmp')
#convert to floating point
mask = np.array(j, dtype=np.float)
mask /= 255.0
#set transparency to 25%
transparency = .25
mask*=transparency
cv2.imshow('img',mask)
cv2.waitKey(0)
#make a green overlay
green = np.ones(img.shape, dtype=np.float)*(0,1,0)
#green over original image
out = green*mask + img*(1.0-mask)
cv2.imshow('img',out)
cv2.waitKey(0)
cv2.destroyAllWindows()
Output image:
One easy way would be with broadcasting after extending matrix to 3D and simply multiplying with the green colour triplet, like so -
matrix[...,None]*[0,255,0]
Sample run -
In [35]: matrix
Out[35]:
array([[1, 0, 0, 0],
[1, 0, 0, 1],
[0, 0, 1, 0]])
In [36]: matrix[...,None]*[0,255,0]
Out[36]:
array([[[ 0, 255, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 0, 0]],
[[ 0, 255, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 255, 0]],
[[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 255, 0],
[ 0, 0, 0]]])
The second column signifying the green colour.
Please note that this is not alpha masking, which generally involves the fourth channel, but is a simple RGB masking.
Another approach with zeros based initialization and might be better on performance -
m,n = matrix.shape
out = np.zeros((m,n,3),dtype=np.uint8)
out[matrix==1,1] = 255 # green channel accessed with the last index being 1