This question is related to this question: How to remove convexity defects in sudoku square
I was trying to implement nikie's answer in Mathematica to OpenCV-Python. But i am stuck at the final step of procedure.
ie I got the all intersection points in square like below:
Now, i want to transform this into a perfect square of size (450,450) as given below:
(Never mind the brightness difference of two images).
Question:
How can i do this in OpenCV-Python? I am using cv2 version.
Apart from etarion's suggestion, you could also use the remap function. I wrote a quick script to show how you can do this. As you see coding this is really easy in Python. This is the test image:
and this is the result after warping:
And here is the code:
import cv2
from scipy.interpolate import griddata
import numpy as np
grid_x, grid_y = np.mgrid[0:149:150j, 0:149:150j]
destination = np.array([[0,0], [0,49], [0,99], [0,149],
[49,0],[49,49],[49,99],[49,149],
[99,0],[99,49],[99,99],[99,149],
[149,0],[149,49],[149,99],[149,149]])
source = np.array([[22,22], [24,68], [26,116], [25,162],
[64,19],[65,64],[65,114],[64,159],
[107,16],[108,62],[108,111],[107,157],
[151,11],[151,58],[151,107],[151,156]])
grid_z = griddata(destination, source, (grid_x, grid_y), method='cubic')
map_x = np.append([], [ar[:,1] for ar in grid_z]).reshape(150,150)
map_y = np.append([], [ar[:,0] for ar in grid_z]).reshape(150,150)
map_x_32 = map_x.astype('float32')
map_y_32 = map_y.astype('float32')
orig = cv2.imread("tmp.png")
warped = cv2.remap(orig, map_x_32, map_y_32, cv2.INTER_CUBIC)
cv2.imwrite("warped.png", warped)
I suppose you can google and find what griddata does. In short, it does interpolation and here we use it to convert sparse mappings to dense mappings as cv2.remap requires dense mappings. We just need to convert to the values to float32 as OpenCV complains about the float64 type. Please let me know how it goes.
Update: If you don't want to rely on Scipy, one way is to implement the 2d interpolation function in your code, for example, see the source code of griddata in Scipy or a simpler one like this http://inasafe.readthedocs.org/en/latest/_modules/engine/interpolation2d.html which depends only on numpy. Though, I'd suggest to use Scipy or another library for this, though I see why requiring only CV2 and numpy may be better for a case like this. I'd like to hear how your final code solves Sudokus.
if you have source points and end points (you only need 4), you can plug them into cv2.getPerspectiveTransform, and use that result in cv2.warpPerspective. Gives you a nice flat result.
Related
I was trying to to learn pca(using the iris dataset) with python and i got some results,so i wanted to test the results ir R to make sure it was good.When i checked the results,it gave me a mirror diagram that of python(in the y axis),and the negative numeric sign in some of the values(python: [140,1]=0.1826089,r[141,2]=-0.1826089[python counts form zero]).
The python code:
import numpy as np
import matplotlib.pyplot as plt
import sklearn.decomposition as p
data=np.loadtxt("sample_data/iris.txt",delimiter=';',usecols=(0,1,2,3))
pca=p.PCA().fit(data)
pcaData=pca.transform(data)
plt.scatter(pcaData[:,0],pcaData[:,1])
print(pcaData[140,1])
My python diagram
The R code:
data=read.csv("C:\\Users\\George\\Desktop\\iris.csv",sep=";",colClasses=c(NA, NA, NA,NA,"NULL"));data=data[-151,]
pca=prcomp(data)
plot(pca$x[,1],pca$x[,2])
print(pca$x[141,2])
My R diagram
In search i did on the internet,i found the same happens.
The R diagram on the internet-Source
The Python diagram on the internet-Source.
I was expecting to be the same.
Is somthing that i do not understand well?
Thank you.
ScikitLearn uses a pseudo-randomized method to determine an approximation of the singular value decomposition.
see https://scikit-learn.org/stable/modules/generated/sklearn.utils.extmath.randomized_svd.html
Therefore, unless you can guarantee that the methods are the same and use the same random seed, you will not obtain exactly the same values for the principal components.
I just tried corner_fast form skimage and it seems to work pretty well for corner detection:
from skimage.feature import corner_fast
np.random.seed(2018)
img = np.random.normal(size=(20, 20))
img_response = corner_fast(img, n=12, threshold=0.0)
The FAST algorithm is explained in numerous places in the web. However, these explanations suggest FAST should return a boolean value (corner or not-corner).
Yet, img_response is a float array. I guess these numbers correspond to how "cornery" a specific pixel is, but, how are they computed? What do they really represent?
Your guess is right, the response image is a sort of accumulator, the higher the value, the more "cornery" the pixel is.
To extract the corners location, you can call the function corner_peaks on the result returned by corner_fast
About the how to is it computed, the documentation gives these two references:
[1] Edward Rosten and Tom Drummond “Machine Learning for high-speed corner detection”, http://www.edwardrosten.com/work/rosten_2006_machine.pdf
[2] Wikipedia, “Features from accelerated segment test”, https://en.wikipedia.org/wiki/Features_from_accelerated_segment_test
Finally, just know that scikit-image is open source and you can therefore go see the details of the code itself https://github.com/scikit-image/scikit-image/tree/master/skimage
I was hoping someone could take a look at this sharpening algorithm I devised using PILLOW and explain to me why it is not giving a desirable sharpening effect on images. It really just looks like crap when applied to my sample images. I've worked on this for several days, but haven't made much progress in either improving the quality of the sharpening effect or the efficiency of the algorithm itself. Ideally, I'm looking for a subtle sharpening effect or something that can be scaled easily. I really appreciate any help or insight that can be provided. Here are the sources that I used to come up with this algorithm:
http://lodev.org/cgtutor/filtering.html#Sharpen
http://www.foundalis.com/res/imgproc.htm
from PIL import *
from PIL import Image
import os
os.chdir(r"C:")
filter1=9
filter2=-1
def sharpen2(photo,height,width,filter1,filter2):
for y in range(1,height-1):
for x in range(1,width-1):
(r,g,b)=photo.getpixel((x,y))
r=int(r*filter1)
g=int(g*filter1)
b=int(b*filter1)
(r1,g1,b1)=photo.getpixel((x-1,y-1))
r1=int(r1*filter2)
g1=int(g1*filter2)
b1=int(b1*filter2)
(r2,g2,b2)=photo.getpixel((x,y-1))
r2=int(r2*filter2)
g2=int(g2*filter2)
b2=int(b2*filter2)
(r3,g3,b3)=photo.getpixel((x+1,y-1))
r3=int(r3*filter2)
g3=int(g3*filter2)
b3=int(b3*filter2)
(r4,g4,b4)=photo.getpixel((x-1,y))
r4=int(r4*filter2)
g4=int(g4*filter2)
b4=int(b4*filter2)
(r5,g5,b5)=photo.getpixel((x+1,y))
r5=int(r5*filter2)
g5=int(g5*filter2)
b5=int(b5*filter2)
(r6,g6,b6)=photo.getpixel((x-1,y+1))
r6=int(r6*filter2)
g6=int(g6*filter2)
b6=int(b6*filter2)
(r7,g7,b7)=photo.getpixel((x,y+1))
r7=int(r7*filter2)
g7=int(g7*filter2)
b7=int(b7*filter2)
(r8,g8,b8)=photo.getpixel((x+1,y+1))
r8=int(r8*filter2)
g8=int(g8*filter2)
b8=int(b8*filter2)
rfPixel=r+r1+r2+r3+r4+r5+r6+r7+r8
if rfPixel>255:
rfPixel=255
elif rfPixel<0:
rfPixel=0
gfPixel= g+g1+g2+g3+g4+g5+g6+g7+g8
if gfPixel>255:
gfPixel=255
elif gfPixel<0:
gfPixel=0
bfPixel=b+b1+b2+b3+b4+b5+b6+b7+b8
if bfPixel>255:
bfPixel=255
elif bfPixel<0:
bfPixel=0
photo.putpixel((x,y),(rfPixel,gfPixel,bfPixel))
return photo
photo=Image.open("someImage.jpg").convert("RGB")
photo2=photo.copy()
height=photo.height
width=photo.width
x=sharpen2(photo,height,width,filter1,filter2)
One problem is likely that you're saving the results to the same image you are getting pixel data from. By the time you get to a pixel, some of its neighbors have been replaced by the filtered data, and some have not. The error is small at first but adds up.
To fix: save the results to a different image, say filtered_photo.putpixel(...). You'd have to create a blank filtered_photo first.
Another big problem (mentioned by #Mark Ransom) is that you probably want filter1 = 1.1 and filter2 = -0.1 or something along those lines. Using 9 and -1 will make most values come out of range.
A better implementation: don't loop over each pixel in python code, use numpy to process the whole image at once, it will be much faster (and shorter code). The usual implementation of sharpen is to subtract the gaussian-filtered image from the original image, which is a one-liner using numpy and ndimage (or skimage).
By writing
import igraph
g = igraph.Graph()
g.add_vertices(6)
g.add_edges([(0,1),(0,3),(0,4),(0,5),(1,2),(2,4),(2,5),(3,0),(3,2),(3,5),(4,5),(3,3)])
A=g.get_adjacency()
I get the adjacency matrix of graph g, as a Matrix object. I want to calculate its eigenvalues by using, for example, numpy.linalg.eigvals(). This method takes a numpy array object as argument.
How do I convert a Matrix object into a numpy array object?
I tried by using
X=numpy.matrix(A)
but it produced some mixture of the two and eigenvalues could not be calculated.
According to the documentation of iGraph's matrix class, you could retrieve the data as a list of lists and then convert easily to a numpy ndarray:
A = g.get_adjacency()
A = np.array(A.data)
Not exactly the answer you're after, but here's how to do it with networkx (option with igraph is below - I think):
import networkx as nx
G= nx.Graph()
G.add_edges_from([(0,1),(0,3),(0,4),(0,5),(1,2),(2,4),(2,5),(3,0),(3,2),(3,5),(4,5),(3,3)])
A=nx.adjacency_matrix(G) #by default A is sparse
import numpy as np
np.linalg.eig(A.todense())
I don't have igraph, so not sure if a similar .todense() might work for the Matrix type it returns.
edit I see some suggestion that
numpy.array(list(g.get_adjacency()))
might do what you're after with igraph. I don't have igraph, so can't test. Please let me know if it works. (but consider networkx anyways ;) )
re-edit I think the solution by Oliver is cleaner. But I still want to leave the networkx version and this other igraph approach for others to see.
I am creating a toolset for creating nurbs curves/surfaces inside maya using python.
I have a set of dictionaries that include cvPositions, knots, form etc. each of which describe a preset 3d shape (cube, circle, pyramid etc).
I also have a 3d matrix stored in the nodes metadata that is used as an offset for the shape. This allows you to scale/move/rotate the shape without moving the transform.
The problem is in the way I am applying this matrix is very slow:
First I will create a new (edit)transform at the position of the (orig)transform containing the curves.
Next I will transfer cv positions in world space from (orig)transform to (edit)transform
Next i will move the (edit)transform into the matrix position.
Finally I will transfer the cvPositions back to the (orig)transform
When creating hundreds of shapes, this is becoming prohibitively slow...
Can someone describe a mathematical way to apply a matrix to a set of 3d points?
Perhaps using one of the math modules or numpy?
Alternatively,
Is there a way using OpenMaya api functions to do this? Perhaps with MPointArray? This is as far as I have gotten on that front:
crv = OpenMaya.MFnNurbsCurve( self.dagPath )
cvs = OpenMaya.MPointArray()
space = OpenMaya.MSpace.kWorld
crv.getCVs(cvs, space)
positions = []
for i in range(cvs.length()):
pt = cvs[i]
positions.append( (pt[0], pt[1], pt[2]) )
The easiest method is to use pymel's built-in versions of points and matrices (pymel is built in to maya 2011+). The math types are in pymel.datatatypes; here's an example of transforming a point by a matrix in pymel:
import pymel.core as pm
pt = pm.datatypes.Point(0,0,0)
mt = pm.datatypes.Matrix(1,0,0,0, 0,1,0,0, 0,0,1,0, 5,5,5,1 )
moved = pt * mt
print moved
# [5,5,5]
Pymel points and matrices will let you do your algorithm. The math is going to be done in the API but the Python <> C++ conversions may still make it feel pretty slow for big data.
It sounds like you're basically re-creating 'freeze transforms' followed by 'zero pivots'. Maybe you should try that as an alternative to doing this in python math...