corner detection in complex image - python-2.7

I would like to find a fixed point in pictures like the above for latter comparison and i thought of taking the upper left corner of the board. I tried some things but the result is shown with the green dot. I would like to find a way to take that dot in the corner of the board, not above. I also want to make that point to be the same in a set of pictures of the same board but with some change in orientation maybe. I am using python 2.7
code i have tried so far:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
edged = cv2.Canny(blurred, 10, 200)
edged = cv2.dilate(edged, None, iterations=6)
edged = cv2.erode(edged, None, iterations=6)
(contourss, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
contourss = sorted(contourss, key=cv2.contourArea, reverse=True)[:10]
cv2.drawContours(image, contourss[0], -1, (0, 255, 0), 2)
rect1 = cv2.minAreaRect(contourss[0])
box1 = cv2.cv.BoxPoints(rect1)
box1 = np.int0(box1)
topleftPer=[]
for i in box1[1]:
topleftPer.append(i)
pt = (topleftPer[0], topleftPer[1])
cv2.circle(image, pt, 5, (0, 255, 0), -1)

Always amazing to see how people want to rely on edge detection. Edge detection is so unreliable !
This image is easy to binarize. Find the black pixel with the smallest value of x+y and place a small ROI around this pixel. Then use the leftmost and topmost coordinates.

Related

OpenCV findContours, how to check colors on both sides

I have an Mat object derived using the canny edge detectors, I extracted contours from such image using the findContours function. Now what I'd like to do for each of such contours would be somehow check the colour on both sides.
For the "colour" bit I've discretized HSI color space, however I'm very confused on how I could "pick the colours" in both sides given a contour.
Is there a way to easily do this?
You can use the image that you apply the Canny edge detector to do this. Take the gradient of that image. Gradient is a vector. As shown in the wiki page image (shown below), the gradient points in the direction of the greatest rate of increase. If you take the negative gradient, then it points in the direction of the greatest rate of decrease. Therefore, if you sample the gradient of the image at contour points, positive and negative gradients at those points should point to the regions either side of contour points. So, you can sample points along these directions to get an idea about the colors you want.
Image gradient:
Sample python code shows how this is done for the simple image shown below. It uses Sobel to calculate the gradient.
Input image:
Canny edges and sampled points:
Green: point on contour
Red: point in the positive gradient direction
Blue: point in the negative gradient direction
import cv2
import numpy as np
from matplotlib import pyplot as plt
im = cv2.imread('grad.png', 0)
dx = cv2.Sobel(im, cv2.CV_32F, 1, 0)
dy = cv2.Sobel(im, cv2.CV_32F, 0, 1)
edge = cv2.Canny(im, 64, 192)
dx = dx / np.sqrt(dx*dx + dy*dy + 0.01)
dy = dy / np.sqrt(dx*dx + dy*dy + 0.01)
r = 20
y, x = np.nonzero(edge)
pos1 = (np.int32(x[128]+r*dx[y[128], x[128]]), np.int32(y[128]+r*dy[y[128], x[128]]))
pos2 = (np.int32(x[128]-r*dx[y[128], x[128]]), np.int32(y[128]-r*dy[y[128], x[128]]))
im2 = cv2.cvtColor(edge, cv2.COLOR_GRAY2BGR)
cv2.circle(im2, pos1, 10, (255, 0, 0), 1)
cv2.circle(im2, pos2, 10, (0, 0, 255), 1)
cv2.circle(im2, (x[128], y[128]), 10, (0, 255, 0), 1)
plt.imshow(im2)

finding rectangles in a pcb using python

Is there any way to find rectangles in a pcb board using python? My goal is to find the pcb components. I tried to smooth the picture and then apply cunny edge and contour detection but the only correct contour that i managed to find is the contour around the board. Is there any way to find the components of the board and draw a rectangle around them? Any help will be highly appreciated! Thank you!
UPDATE
The code i used is about trying to find contours based on color.
import numpy as np
import cv2
from matplotlib import pyplot as plt
im = cv2.imread('img14.jpg')
#gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
#ret, thresh = cv2.threshold(gray, 80, 255, 0)
#blur = cv2.bilateralFilter(img,9,75,75)
kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(im,-1,kernel)
# find all the 'black' shapes in the image
lower = np.array([0, 0, 0])
upper = np.array([100, 100, 100])
shapeMask = cv2.inRange(dst, lower, upper)
(cnts, _) = cv2.findContours(shapeMask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
print "I found %d black shapes" % (len(cnts))
for c in cnts:
cv2.drawContours(im, [c], -1, (0, 255, 0), 2)
cv2.imshow('shapemask', shapeMask)
cv2.imshow('contours', im)
cv2.waitKey(0)
it print that 322 contours have been found and that's the problem. I need only the 8 biggest. Is there any way to take only those with the biggest area? Or maybe i have to process the image first for better results?

Python cv2 Image Pyramids

Trying to implement the famous Orange/Apple pyramids blending (cv2 Image Pyramids).
Note: Both images shape is 307x307.
However, since the result image is blurred due to clipping values in cv2.subtract and cv2.add (as stated in cv2 vs numpy Matrix Arithmetics), I have used numpy arithmetics instead as suggested in StackOverflow: Reconstructed Image after Laplacian Pyramid Not the same as original image.
I have tested this by performing pyramids on one image and the result image constructed back using pyramids has the same Max,Min,Average pixels values as opposed to using cv2 arithmetics.
However, on pyramids level 7, the result image gets a 'noise' of a red dot and on level 9 the result image gets a lot of green pixels noises. Images of levels 6, 7, 9 - Imgur Album.
Any ideas why would this happen? The pyramid level 9 green noise I would say happened because the image went below 1x1 shape. But what about the red dot on 7 level pyramid?
EDIT : Code Added
numberOfPyramids = 9
# generate Gaussian pyramids for A and B Images
GA = A.copy()
GB = B.copy()
gpA = [GA]
gpB = [GB]
for i in xrange(numberOfPyramids):
GA = cv2.pyrDown(GA)
GB = cv2.pyrDown(GB)
gpA.append(GA)
gpB.append(GB)
# generate Laplacian Pyramids for A and B Images
lpA = [gpA[numberOfPyramids - 1]]
lpB = [gpB[numberOfPyramids - 1]]
for i in xrange(numberOfPyramids - 1, 0, -1):
geA = cv2.pyrUp(gpA[i], dstsize = np.shape(gpA[i-1])[:2])
geB = cv2.pyrUp(gpB[i], dstsize = np.shape(gpB[i-1])[:2])
laplacianA = gpA[i - 1] - geA if i != 1 else cv2.subtract(gpA[i-1], geA)
laplacianB = gpB[i - 1] - geB if i != 1 else cv2.subtract(gpB[i-1], geB)
lpA.append(laplacianA)
lpB.append(laplacianB)
# Now add left and right halves of images in each level
LS = []
for la, lb in zip(lpA, lpB):
_, cols, _ = la.shape
ls = np.hstack((la[:, : cols / 2], lb[:, cols / 2 :]))
LS.append(ls)
# now reconstruct
ls_ = LS[0]
for i in xrange(1, numberOfPyramids):
ls_ = cv2.pyrUp(ls_, dstsize = np.shape(LS[i])[:2])
ls_ = ls_ + LS[i] if i != numberOfPyramids - 1 else cv2.add(ls_, LS[i])
cv2.imshow(namedWindowName, ls_)
cv2.waitKey()
After read the original article about laplacian pyramid, I find I misunderstood this method, we can fully reconstruct the original image without blur, because we use of additional pix information. And It is true that clipping value lead to blurred. Well now we come back to the beginning again :)
So the code you post is still clipping value, I advise you use int16 to save the laplacian pyramid, and not use cv2.subtract. Hope it works.

Python DBN dbn.predict use

Hi I am confused with how dbn.predict works I have detected a number in an image using canny and then otsu threshold and resized it to 28x28 etc however when I pass it to dbn.predict I get the following error
ValueError: arrays not aligned for dot product. a dot product was requested of arrays with shapes (1, 28) and (784, 300)
Here is the code for the same, thanks in advance
(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# sort the contours by their x-axis position, ensuring
# that we read the numbers from left to right
cnts = sorted([(c, cv2.boundingRect(c)[0]) for c in cnts], key = lambda x: x[1])
# loop over the contours
for (c, _) in cnts:
# compute the bounding box for the rectangle
(x, y, w, h) = cv2.boundingRect(c)
# if the width is at least 7 pixels and the height
# is at least 20 pixels, the contour is likely a digit
if w >= 7*scaler and h >= 25*scaler:
# crop the ROI and then threshold the grayscale
# ROI to reveal the digit
roi = gray[y:y + h, x:x + w]
thresh = roi.copy()
T = mahotas.thresholding.otsu(roi)
thresh[thresh > T] = 255
thresh = cv2.bitwise_not(thresh)
#thresh = dataset.deskew(thresh, 28)
#thresh = dataset.center_extent(thresh, (28, 28))
#print thresh.size
#cv2.imshow("Thresh", thresh)
# Resize the image
roi = cv2.resize(thresh, (28, 28), interpolation=cv2.INTER_AREA)
roi = cv2.dilate(roi, (3, 3))
print roi.size
cv2.imshow("ROI", roi)
cv2.waitKey(0)
# Calculate the HOG features
roi_hog_fd = hog(roi, orientations=9, pixels_per_cell=(28, 28), cells_per_block=(1, 1), visualise=False)
nbr = clf.predict(np.array([roi_hog_fd], 'float64'))
pred = dbn.predict(np.atleast_2d(roi/255))

Transform Rectangle to trapezoid for perspective

I have picture from front-view. and I want to turn this into bird's eye view.
Now I want to calculate for each point in the rectangle (x,y) what will be transformed x,y in the trapezoid.
there must be a formula for this transformation with a given x and y and also the angle of the trapezoid (a).
I am programming in C and using opencv.
Thanks a lot in advance.
Did you consider the homography transform. You use this to create or correct perspective in an image, I think that it is exactly what you want.
With OpenCV, you can use the method cv::findHomography(). The arguments are the 4 initial points (vertices of your rectangle) and the 4 final points (the vertices of the trapeze). You get a transformation matrix that you can then use with cv::warpPerspective() or cv::perspectiveTransform().
I was able to figure out a way for your problem.
Here is the code I used for the same:
Importing the required packages:
import cv2
import numpy as np
Reading the image to be used:
filename = '1.jpg'
img = cv2.imread(filename)
cv2.imwrite('img.jpg',img)
Storing the height and width of the image in separate variables:
ih, iw, _ = img.shape
Creating a black window whose size is bigger than that of the image and storing its height and width in separate variables:
black = np.zeros((ih + 300, iw + 300, 3), np.uint8)
cv2.imwrite('black.jpg',black)
bh, bw, _ = black.shape
Storing the 4 corner points of the image in an array:
pts_src = np.array([[0.0, 0.0],[float(iw), 0.0],[float(iw), float(ih)],[0.0,float(ih)]])
Storing the 4 corner points of the trapezoid to be obtained:
pts_dst = np.array([[bw * 0.25, 0],[bw * 0.75, 0.0],[float(bw), float(bh)],[0.0,float(bh)]])
Calculating the homography matrix using pts_src and pts_dst:
h, status = cv2.findHomography(pts_src, pts_dst)
Warping the given rectangular image into the trapezoid:
im_out = cv2.warpPerspective(img, h, (black.shape[1],black.shape[0]))
cv2.imwrite("im_outImage.jpg", im_out)
cv2.waitKey(0)
cv2.destroyAllWindows()
If you alter the values in the array pts_dst you will be able to get different kinds of quadrilaterals.