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.
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
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.
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 am trying to repair image contains letters each letter split into two halves from the middle.
original Image
After Applying the following code:
gray = cv2.cvtColor(cropped_bot, cv2.COLOR_BGR2GRAY)
new_img = ((gray >= 230)*255).astype('uint8')
bottom_image = 255-new_img
I get this Image
My Problem is to fix the line that split the letters into two part.
I have tried adaptiveThreshold
cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 15, 2)
But it doesn't help. How I can solve this
Here are a few steps you can follow:
Perform Otsu threshold on the gray scale image
Apply morphological close operation with a kernel
Code :
ret, thresh1 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
cv2.imshow('thresh1', thresh1)
k = np.array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], np.uint8)
closing = cv2.morphologyEx(thresh1, cv2.MORPH_CLOSE, k)
cv2.imshow(closing, closing)
UPDATE:
k1 = np.ones((3, 3), np.uint8)
erosion = cv2.erode(closing, k1, iterations = 1)
cv2.imshow(erosion, erosion)