Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added normalized graph cut #8

Closed
wants to merge 3 commits into from

Conversation

tejus-gupta
Copy link
Contributor

Segments graph using recursive two-way normalized graph cut as described in this paper - Normalized Cuts and Image Segmentation

@tejus-gupta
Copy link
Contributor Author

Since adjacency matrix for grid connectivity based graphs are sparse, the paper used Lanczos solver. For small matrices eigs(D-W, D, nev = 2) (this uses Lanczos solver for real symmetric matrices) wasn't giving accurate results. What could I be doing wrong? Should I read how Lanczos algorithm works? This step is the slowest step in the algorithm.

@timholy
Copy link
Member

timholy commented Jul 24, 2017

I assume you're using the eigs implementation in Base? If you have a good test case that demonstrates the problem, I'd definitely report it as a bug. There are folks who know that part of Julia better than me, and perhaps they might help. I assume you noticed the tol and maxiter keyword arguments, but they didn't help?

One other general comment: since this is purely graph-theoretical, have you considered whether this part of the algorithm should live in a different repository? I'm not at all opposed to having it here, but if it's of use outside of image processing perhaps it would be better in a graphs-oriented package?

@tejus-gupta
Copy link
Contributor Author

As far I know, the normalized graph-cut problem and the algorithm were first introduced in the context of image segmentation. If this algorithm is more generally used, I agree that this should be in a graph-oriented package.

@timholy
Copy link
Member

timholy commented Jul 27, 2017

From reading the algorithm, to me it looks generally useful. Perhaps @sbromberger could comment?

@sbromberger
Copy link

This looks very interesting.

@tejus-gupta - We'd have to adapt it a bit to be generally applicable to LightGraphs, but if you're up for the discussion, please feel free to file a WIP PR at https://github.com/JuliaGraphs/LightGraphs.jl and we can start the review.

One thing to start: we should not assume that weights will always return a SparseMatrixCSC – the guarantee is that it's something that is "Array-like" (supports a 2-dimensional getindex.

@sbromberger
Copy link

cc @jpfairbanks to weigh in here since this is squarely in one of his (many) areas of expertise.

end

#get eigenvector corresponding to second smallest eigenvalue
v = eigvecs(full(D-W), full(D))[:, 2]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could replace this with

\lambda,  vs = eigs(CombinatorialLaplacian(g), nev=2, which=:SM)
v = v[:,2]

min_cost = cost
best_thres = t
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can optimize this to use matrix permutation and one matrix vector product to calculate all nv(g) possible cuts at once. But this one works well enough for large ncuts.

@timholy
Copy link
Member

timholy commented Aug 14, 2017

I interpret the above discussion as saying that the core graph algorithm should live in LightGraphs, and the image-related preparation/postprocessing can go here. Please link any LightGraphs PR to this issue.

@jpfairbanks
Copy link

@timholy Yes, normalized graph cut is a generic graph algorithm that can go in lightgraphs. The parts that are image specific would be calculating the edge set and weights from the pixel values. We would not want an algorithm in lightgraphs that took an image as the input. But once you have extracted a graph (with or without weights), then LG can take over. Turning the segments back into sets of pixel locations or whatever you want to do with them should live in this package.

@tejus-gupta
Copy link
Contributor Author

tejus-gupta commented Aug 16, 2017

I am sorry for the delayed reply. I will open the pull request right away.

@timholy
Copy link
Member

timholy commented Oct 5, 2018

Is this entirely superseded by sbromberger/LightGraphs.jl#736, or is there an image-specific component here?

@tejus-gupta
Copy link
Contributor Author

I didn't include the code for constructing a region adjacency graph from an image and so this is entirely replaced by sbromberger/LightGraphs.jl#736.

I think we should add a generic function to create a region adjacency graph from an image and advice the user to use graph clustering methods available in other packages.
G = region_adjacency_graph(img, weight_fn, r) will construct graph G with nodes as each pixel in img and edges between each pair of pixel index i and j if |i-j|<r with weight weight_fn(i, img[i], j, img[j]). We can include an example of constructing G from an image and using normalized_cut to segment it.

@timholy
Copy link
Member

timholy commented Oct 8, 2018

Thanks. I'll close this, and we can implement those good ideas in separate PRs.

@timholy timholy closed this Oct 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants