My question does not refer to what operators I need to use to manipulate matrices, but rather what is actually being sought by doing this procedure.
I have, for example, an image in matrix form on which I need to perform several operations (this filter is one of them). After converting said image to grayscale, I need to apply the following filter
float[][] smoothKernel = {
{0.1f,0.1f,0.1f},
{0.1f,0.2f,0.1f},
{0.1f,0.1f,0.1f}
};
on it.
The assignment file gives this example , so I assumed that when asked to "smooth" the image, I had to replace every individual pixel with an average of its neighbors (while also making sure special cases such as corners or side were handled properly).
The basic idea is this:
public static float[][] filter(float[][] gray, float[][] kernel) {
// gray is the image matrix, and kernel is the array I specifed above
float current = 0.0f;
float around = 0.0f;
float[][] smooth = new float[gray.length][gray[0].length];
for (int col = 0; col < gray.length; col++) {
for (int row = 0; row < gray[0].length; row++) {
//first two for loops are used to do this procedure on every single pixel
//the next two call upon the respective pixels around the one in question
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
around = at(gray, i + col, j + row); //This calls a method which checks for the
//pixels around the one being modified
current += around * kernel[i+1][j+1];
//after the application of the filter these are then added to the new value
}
}
smooth[col][row] = current;
current = 0.0f;
//The new value is now set into the smooth matrix
}
}
return smooth;
}
My dilemma lies in if I have to create this new array float[][] smooth; so as to avoid overriding the values of the original (the image outputted is all white in this case...). From the end product in the example I linked above I just cannot understand what is going on.
What is the correct way of applying the filter? Is this a universal method or does it vary for different filters?
Thank you for taking the time to clarify this.
EDIT: I have found the two errors which I detailed in the comments below, implemented back into the code, everything is working fine now.
I have also been able to verify that some of the values in the example are calculated incorrectly (thus contributing to my confusion), so I will be sure to point it out in my next class.
Question has been solved by ulterior methods, I am however not deleting it in hopes other people can benefit from it. The original code can be found in the edits.
A more advanced colleague of mine helped me to note that I was missing two things: one was the issue with resetting the current variable after computing the "smoothed" variables in the new array (resulting in a white image because this value would get increasingly larger thus surpassing the binary color limit, so it was set to the max). The second issue was that I was continuously iterating on the same pixel, which caused the whole image to have the same color (I was iterating the new array). So I added these specifications in, and all works fine since.
Next to my topic ( getPerspectiveTransform on a non entire quadrangle ), I'm finding a way to track little dots white on edges table in most of cases. If I use binary threshold, it works only if I choose arbitrarily the threshold. Problem is that edges color table are very influenced by the light. So I decided to convert my image on HSV and use InRange function which keeps only pixels which are between values my program determines (I adapt theses values based on mean value of edge table (brown in most of cases...)). This function returns a matrice where pixels between the range are set to 255, else 0.
I want to inverse this matrice, I mean switch pixels with val=0 to 255 and pixel with val=255 to 0. Here is my simple code (it doesn't work, it does nothing) :
for (int i=0; i<mat.rows(); i++){
for (int j=0; j<mat.cols(); j++){
if (mat.get(i,j).get(0)[0] == 0){
mat.put(i,j,255);
}
else {
mat.put(i,j,0);
}
}
}
If someone know how to do that in JAVA, it would be nice.
I have a set of rectangles and I would like to "reduce" the set so I have the fewest number of rectangles to describe the same area as the original set. If possible, I would like it to also be fast, but I am more concerned with getting the number of rectangles as low as possible. I have an approach now which works most of the time.
Currently, I start at the top-left most rectangle and see if I can expand it out right and down while keeping it a rectangle. I do that until it can't expand anymore, remove and split all intersecting rectangles, and add the expanded rectangle back in the list. Then I start the process again with the next top-left most rectangle, and so on. But in some cases, it doesn't work. For example:
With this set of three rectangles, the correct solution would end up with two rectangles, like this:
However, in this case, my algorithm starts by processing the blue rectangle. This expand downwards and splits the yellow rectangle (correctly). But then when the remainder of the yellow rectangle is processed, instead of expanding downwards, it expands right first and takes back the portion that was previously split off. Then the last rectangle is processed and it can't expand right or down, so the original set of rectangles is left. I could tweak the algorithm to expand down first and then right. That would fix this case, but it would cause the same problem in a similar scenario that was flipped.
Edit: Just to clarify, the original set of rectangles do not overlap and do not have to be connected. And if a subset of rectangles are connected, the polygon which completely covers them can have holes in it.
Despite the title to your question, I think you’re actually looking for the minimum dissection into rectangles of a rectilinear polygon. (Jason’s links are about minimum covers by rectangles, which is quite a different problem.)
David Eppstein discusses this problem in section 3 of his 2010 survey article Graph-Theoretic Solutions to Computational Geometry Problems, and he gives a nice summary in this answer on mathoverflow.net:
The idea is to find the maximum number of disjoint axis-parallel diagonals that have two concave vertices as endpoints, split along those, and then form one more split for each remaining concave vertex. To find the maximum number of disjoint axis-parallel diagonals, form the intersection graph of the diagonals; this graph is bipartite so its maximum independent set can be found in polynomial time by graph matching techniques.
Here’s my gloss on this admirably terse description, using figure 2 from Eppstein’s article. Suppose we have a rectilinear polygon, possibly with holes.
When the polygon is dissected into rectangles, each of the concave vertices must be met by at least one edge of the dissection. So we get the minimum dissection if as many of these edges as possible do double-duty, that is, they connect two of the concave vertices.
So let’s draw the axis-parallel diagonals between two concave vertices that are contained entirely within the polygon. (‘Axis-parallel’ means ‘horizontal or vertical’ here, and a diagonal of a polygon is a line connecting two non-adjacent vertices.) We want to use as many of these lines as possible in the dissection as long as they don’t intersect.
(If there are no axis-parallel diagonals, the dissection is trivial—just make a cut from each concave vertex. Or if there are no intersections between the axis-parallel diagonals then we use them all, plus a cut from each remaining concave vertex. Otherwise, read on.)
The intersection graph of a set of line segments has a node for every line segment, and an edge joins two nodes if the lines cross. Here’s the intersection graph for the axis-parallel diagonals:
It’s bipartite with the vertical diagonals in one part, and the horizontal diagonals in the other part. Now, we want to pick as many of the diagonals as possible as long as they don’t intersect. This corresponds to finding the maximum independent set in the intersection graph.
Finding the maximum independent set in a general graph is an NP-hard problem, but in the special case of a bipartite graph, König’s theorem shows that it’s equivalent to the problem of finding a maximum matching, which can be solved in polynomial time, for example by the Hopcroft–Karp algorithm. A given graph can have several maximum matchings, but any of them will do, as they all have the same size. In the example, all the maximum matchings have three pairs of vertices, for example {(2, 4), (6, 3), (7, 8)}:
(Other maximum matchings in this graph include {(1, 3), (2, 5), (7, 8)}; {(2, 4), (3, 6), (5, 7)}; and {(1, 3), (2, 4), (7, 8)}.)
To get from a maximum matching to the corresponding minimum vertex cover, apply the proof of König’s theorem. In the matching shown above, the left set is L = {1, 2, 6, 7}, the right set is R = {3, 4, 5, 8}, and the set of unmatched vertices in L is U = {1}. There is only one alternating path starting in U, namely 1–3–6, so the set of vertices in alternating paths is Z = {1, 3, 6} and the minimum vertex cover is thus K = (L \ Z) ∪ (R ∩ Z) = {2, 3, 7}, shown in red below, with the maximum independent set in green:
Translating this back into the dissection problem, this means that we can use five axis-parallel diagonals in the dissection:
Finally, make a cut from each remaining concave vertex to complete the dissection:
Today I found O(N^5) solution for this problem, and I will share it here.
For the first step, you need to find a way to get the sum of any rectangle in a matrix, with complexity O(1). It's pretty easy to do.
Now for the second step, you need to know dynamic programming. The idea is to store a rectangle and break it into smaller pieces. If the rectangle is empty, you can return 0. And if it's filled, return 1.
There are N^4 states to store the rectangle, plus the O(N) complexity for each state... So you will get an O(N^5) algorithm.
Here's my code. I think it will help.
The input is simple. N, M (size of matrix)
After that, the following N lines will have 1s and 0s.
Example:
4 9
010000010
111010111
101111101
000101000
#include <bits/stdc++.h>
#define MAX 51
int tab[MAX][MAX];
int N,M;
int sumed[MAX][MAX];
int t(int x,int y) {
if(x<0||y<0)return 0;
return sumed[x][y];
}
int subrec(int x1,int y1,int x2,int y2) {
return t(x2,y2)-t(x2,y1-1)-t(x1-1,y2)+t(x1-1,y1-1);
}
int resp[MAX][MAX][MAX][MAX];
bool exist[MAX][MAX][MAX][MAX];
int dp(int x1,int y1,int x2,int y2) {
if(exist[x1][y1][x2][y2])return resp[x1][y1][x2][y2];
exist[x1][y1][x2][y2]=true;
int soma = subrec(x1,y1,x2,y2);
int area = (x2-x1+1)*(y2-y1+1);
if(soma==area){return resp[x1][y1][x2][y2]=1;}
if(!soma) {return 0;}
int best = 1000000;
for(int i = x1;i!=x2;++i) {
best = std::min(best,dp(x1,y1,i,y2)+dp(i+1,y1,x2,y2));
}
for(int i = y1;i!=y2;++i) {
best = std::min(best,dp(x1,y1,x2,i)+dp(x1,i+1,x2,y2));
}
return resp[x1][y1][x2][y2]=best;
}
void backtracking(int x1,int y1,int x2,int y2) {
int soma = subrec(x1,y1,x2,y2);
int area = (x2-x1+1)*(y2-y1+1);
if(soma==area){std::cout<<x1+1<<" "<<y1+1<<" "<<x2+1<<" "<<y2+1<<"\n";return;}
if(!soma) {return;}
int best = 1000000;
int obj = resp[x1][y1][x2][y2];
for(int i = x1;i!=x2;++i) {
int ans = dp(x1,y1,i,y2)+dp(i+1,y1,x2,y2);
if(ans==obj){
backtracking(x1,y1,i,y2);
backtracking(i+1,y1,x2,y2);
return;
}
}
for(int i = y1;i!=y2;++i) {
int ans = dp(x1,y1,x2,i)+dp(x1,i+1,x2,y2);
if(ans==obj){
backtracking(x1,y1,x2,i);
backtracking(x1,i+1,x2,y2);
return;
}
}
}
int main()
{
std::cin >> N >> M;
for(int i = 0; i != N;++i) {
std::string s;
std::cin >> s;
for(int j = 0; j != M;++j) {
if(s[j]=='1')tab[i][j]++;
}
}
for(int i = 0; i != N;++i) {
int val = 0;
for(int j = 0; j != M;++j) {
val += tab[i][j];
sumed[i][j]=val;
if(i)sumed[i][j]+=sumed[i-1][j];
}
}
std::cout << dp(0,0,N-1,M-1) << std::endl;
backtracking(0,0,N-1,M-1);
}
I have 2 images as following:
I would like to combine them automatically, hopefully it can be done in Java
How to detect the pixel location and correct edges to combine both images, due to both images have overlapping and without knowing which is the correct edges to combine? Any algorithm can be provided?
ImageJ is a very good java image processing library. It may have plugins out there to do this already so perhaps worth a check.
I would start by trying to find a location in both images that is the same. Do a line profile across both images vertically and see if the pixel values and y values are the same. If the images are exactly the same in only one location then it should be easy. If there are multiple locations where the pixels are the same or the pixels in the y direction are never the same then I think your problem may not have a uniquie solution.
Here is some code to get you started
public class CombineImages implements PlugIn
{
#Override
public void run(String arg0) {
// TODO Auto-generated method stub
}
public ImagePlus combineImages(ImageProcessor ip1, ImageProcessor ip2){
//Get a line of Y pixel values for the first image for each x position and add them to a list
ArrayList<Roi> roiList1 = new ArrayList<Roi>();
for(int i=0; i<ip1.getWidth()-1; i++){
Roi roi = new Roi(i,i+1,1, ip1.getHeight());
roiList1.add(roi);
}
//Get a line of Y pixel values for the second image for each x position and add them to a list
ArrayList<Roi> roiList2 = new ArrayList<Roi>();
for(int i=0; i<ip2.getWidth()-1; i++){
Roi roi = new Roi(i,i+1,1, ip2.getHeight());
roiList2.add(roi);
}
//Check if these are the same and return the X values for both images that these correspond to
//You can then crop and combine the pixel values
return null;
}
}
Im trying to create a program that finds images that are similar to each other and i found a site ( http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html ) that gives steps for making a function that creates a fingerprint of an image, the first step is to reduce the size of the image to a 8 by 8 ( 64 pixel ) image, but i cant figure out how to convert a group of pixels into one pixel e.g.
[(R,G,B)][(R,G,B)][(R,G,B)]
[(R,G,B)][(R,G,B)][(R,G,B)]
[(R,G,B)][(R,G,B)][(R,G,B)]
take this group of pixels, each pixel has a diffrent R, G and B value, how can i take them all and turn them into one set of values e.g.
[(R,G,B)]
I thought maybe add all the R, G and B values up and then average them but that seemed to simple, dose anyone know how to do this ? i am writing this program in java.
There are a lot of different interpolation/re-sampling techniques to do downscaling - you can choose one depending on what results you're expecting. A simple one i.e. is the Nearest neighbour interpolation: But this wouldn't lead to very detailed results, due to the simplicity.
More advanced techniques i.e. linear interpolation, biliniear interpolation or bicubic interpolation are way better suitable, if the pictures are actually photos (rather than i.e. pixelart). But the downscaled image in the link hasn't much details left either - so Nearest neighbor seems quite sufficient (at least to start with).
public int[] resizePixels(int[] pixels,int w1,int h1,int w2,int h2) {
int[] temp = new int[w2*h2] ;
double x_ratio = w1/(double)w2 ;
double y_ratio = h1/(double)h2 ;
double px, py ;
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
px = Math.floor(j*x_ratio) ;
py = Math.floor(i*y_ratio) ;
temp[(i*w2)+j] = pixels[(int)((py*w1)+px)] ;
}
}
return temp ;
}
This java function takes an array of pixel values (original size - w1 and h1) and returns an nearest neighbour (up/down)-scaled array of pixels with dimensions w2 x h2. See also: here.