I was wondering how to make this opencv c++ code in Java
uchar *ptr = eye.ptr<uchar>(y);
I have been looking around and I think I can use the uchar as a byte... but I have no idea what the code to get the .ptr in java
Heres my code so far
private Rect getEyeball(Mat eye, MatOfRect circles) {
int[] sums = new int[circles.toArray().length];
for (int y = 0; y < eye.rows(); y++) {
// OpenCV method uchar *ptr = eye.ptr<uchar>(y); Goes here
}
int smallestSum = 9999999;
int smallestSumIndex = -1;
for (int i = 0; i < circles.toArray().length; i++) {
if (sums[i] < smallestSum) {
smallestSum = sums[i];
smallestSumIndex = i;
}
}
return circles.toArray()[smallestSumIndex];
}
The full C++ code is
cv::Vec3f getEyeball(cv::Mat &eye, std::vector<cv::Vec3f> &circles)
{
std::vector<int> sums(circles.size(), 0);
for (int y = 0; y < eye.rows; y++)
{
uchar *ptr = eye.ptr<uchar>(y);
for (int x = 0; x < eye.cols; x++)
{
int value = static_cast<int>(*ptr);
for (int i = 0; i < circles.size(); i++)
{
cv::Point center((int)std::round(circles[i][0]), (int)std::round(circles[i][1]));
int radius = (int)std::round(circles[i][2]);
if (std::pow(x - center.x, 2) + std::pow(y - center.y, 2) < std::pow(radius, 2))
{
sums[i] += value;
}
}
++ptr;
}
}
int smallestSum = 9999999;
int smallestSumIndex = -1;
for (int i = 0; i < circles.size(); i++)
{
if (sums[i] < smallestSum)
{
smallestSum = sums[i];
smallestSumIndex = i;
}
}
return circles[smallestSumIndex];
}
Distilling down your C++:
for (int y = 0; y < eye.rows; y++)
{
uchar *ptr = eye.ptr<uchar>(y);
for (int x = 0; x < eye.cols; x++)
{
int value = static_cast<int>(*ptr);
// A loop not using ptr.
++ptr;
}
}
You're simply getting the pixel value at (x,y) from eye.
So, just use one of the overloads of Mat.get.
int[] values = new int[eye.channels()];
for (int y = 0; y < eye.rows(); y++) {
for (int x = 0; x < eye.cols(); x++) {
eye.get(x, y, values);
int value = values[0];
// A loop not using ptr.
}
}
Note that using get(int, int, int[]) rather than get(int, int) here means that you avoid allocating a new array for each iteration, which will make things a heck of a lot faster.
Related
I was tasked with creating an image database, which has image objects of several types. Each image is consisted of a 2D array of pixels. I have been asked to create this method:
MatchPattern (Image subimage, Image image): this function returns integer that represent how many times a subimage repeats into an image.
The code I have written is as follows:
public int MatchPattern(Image subimage, Image image) {
if(image.getClass().equals(subimage.getClass())){
int numOfMatches = 0;
int imgWidth = image.getWidth();
int imgHeight = image.getHeight();
int subimgWidth = subimage.getWidth();
int subimgHeight = subimage.getHeight();
if (imgWidth < subimgWidth || imgHeight < subimgHeight)
return 0;
for (int i = 0; i < imgHeight; i++) {
for (int j = 0; j < imgWidth; j++) {
int subHeightIndex = 0;
int subWidthIndex = 0;
Pixel imagePix = image.getImg()[i][j];
Pixel subimgPix = subimage.getImg()[subHeightIndex][subWidthIndex];
if( (imagePix.compareTo(subimgPix)==0) && ((imgWidth-j)>=subimgWidth) && ((imgHeight-i)>=subimgHeight) ){
boolean matchFlag = true;
for (int k = 0; k < subimgHeight; k++) {
if(matchFlag == false)
break;
for (int l = 0; l < subimgWidth; l++) {
matchFlag = (image.getImg()[i+k][j+l] == subimage.getImg()[k][l]);
if (matchFlag == false)
break;
}
}
if(matchFlag == true)
numOfMatches++;
}
}
}
return numOfMatches;
}
return 0;
However, whenever I run the method, it always returns a num of matches equals to 0. Can anybody point me to the right direction?
Thank you in advance.
Shouldn't "k" be compared to "subimgWidth" and "l" to "subimgHeight"?
Also, don't compare the pixels with "==", compare them with ".equals" or with ".compareTo", like you did on the other if statement.
There were a few other things wrong with the algorithm. I tested this with a few sample inputs, and it seems to work well:
public int matchPattern(Image subimage, Image image)
{
int numOfMatches = 0;
int imgWidth = image.getWidth();
int imgHeight = image.getHeight();
int subimgWidth = subimage.getWidth();
int subimgHeight = subimage.getHeight();
if (imgWidth < subimgWidth || imgHeight < subimgHeight)
{
return 0;
}
for (int i = 0; i <= imgWidth - subimgWidth; i++)
{
for (int j = 0; j <= imgHeight - subimgHeight; j++)
{
int subHeightIndex = 0;
int subWidthIndex = 0;
Pixel imagePix = image.getImg()[i][j];
Pixel subimgPix = subimage.getImg()[subHeightIndex][subWidthIndex];
if ((imagePix.compareTo(subimgPix) == 0) && ((imgWidth - j) >= subimgWidth) && ((imgHeight - i) >= subimgHeight))
{
boolean matchFlag = true;
for (int k = 0; k < subimgWidth; k++)
{
for (int l = 0; l < subimgHeight; l++)
{
matchFlag = 0 == (image.getImg()[i + k][j + l].compareTo(subimage.getImg()[k][l]));
if (!matchFlag)
{
break;
}
}
}
if (matchFlag)
{
numOfMatches++;
}
}
}
}
return numOfMatches;
}
This code is the bare-bones of a Minesweeper game board class I'm making. However, this only displays the first row of the array when I display the board. I have looked at this code for so long, and can't see where I'm going wrong with the two-dimensional array. Any help is appreciated
public class Board {
private Cell[][] cells;
public Board(PApplet p, int rows, int columns, double bombChance) {
cells = new Cell[rows][columns];
for (int r = 0; r < cells.length; r++) {
for (int c = 0; c < cells[r].length; c++) {
double randomSeed = Math.random();
if (randomSeed < bombChance) {
cells[r][c] = new BombCell(p);
} else {
cells[r][c] = new SafeCell(p);
}
}
}
}
public void display() {
double tempX = 0;
double tempY = 0;
double size = 50;
for (int r = 0; r < cells.length; r++) {
for (int c = 0; c < cells[r].length; c++) {
cells[r][c].display(tempX, tempY, size);
tempX += 50;
}
tempY += 50;
}
}
}
It appears that you are failing to reset tempX when you start to render the next row.
This may fix your issue:
public void display() {
double tempX = 0;
double tempY = 0;
double size = 50;
for (int r = 0; r < cells.length; r++) {
for (int c = 0; c < cells[r].length; c++) {
cells[r][c].display(tempX, tempY, size);
tempX += 50;
}
tempY += 50;
tempX = 0; // <-------------- look here
}
}
I have this problem, i have a NxM matrix and i want to multiply it by a 3x3 matrix just as a convolutional matrix multiplication
example in this link
This are the code of the matrix:
int width = img.getWidth();
int height = img.getHeight();
int matrix[][] = new int[width][height];
int edgeMatrix[][] = {
{-1,-1,-1},
{-1,8,-1},
{-1,-1,-1}
};
This is the code of the cycle:
for (int x = 0; x < width; x++) {
w = 0;
holderX = x;
for (w = 0; w < 3; w++) {
v = 0;
if (w > 0)
x++;
for (v = 0; v < 3; v++) {
sum = sum + matrix[v][x] * edgeMatrix[v][w];
if (w == 2 && v == 2)
x = holderX;
}
}
}
This cycle already multiply the first "row" of 3 of the matrix.
T tried in a different ways to achieve this but i just cant get that when the matrix reach the end of the width automatically the N value increase one and then starts over again and in the same time the value still working on the internal matrix multiplication.
Thanks for the help.
You dont need holderX, but need one more loop.
int width = img.getWidth();
int height = img.getHeight();
int input[][] = img.getPixels(); // or whatever api you use
int output[][] = new int[height][width];
int kernel[][] = {
{-1,-1,-1},
{-1,8,-1},
{-1,-1,-1}
};
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int accumulator = 0;
for (int v = 0; v < 3; v++) {
for (int w = 0; w < 3; w++) {
int sy = y + v - 1;
int sx = x + w - 1;
if (sy >= 0 && sy < height && sx >= 0 && sx < width)) {
accumulator += input[sy][sx] * kernel[v][w];
}
}
}
output[sy][sx] = accumulator;
}
}
I have a class with three fields:
public class CCTest {
public double f;
public double[][][] x;
public double counter;
}
I am trying to assign a random number to it. I have the method below for random data generation:
public static double[][][] getRandomX(int x, int y, int z) {
double[][][] result = new double[x][y][z];
Random r = new Random();
for (int i = 0; i < z; i++) {
for (int j = 0; j < y; j++) {
for (int k = 0; k < x; k++) {
result[k][j][i] = r.nextDouble();
}
}
}
// System.out.println(Arrays.deepToString(result));
return result;
}
As for the issue. I have for example an array with 5 CCTest-objects:
CCTest[] cls = new CCTest[5];
How can I assign a random number to each of the 5 CCTest-objects?
I tried this:
for (int i = 0; i < Size =5; i++) {
cls[i].x = new double[this.c][this.D][this.Size];
for (int j = 0; j < this.D; j++) {
cls[i].X= getRandomX(this.c, this.D, this.Size);
}
The result should have following structure:
X(:,:,1) =
0.8909 0.5472
0.9593 0.1386
X(:,:,2) =
0.1493 0.8407
0.2575 0.2543
But the code did not produce it. Could anyone guide me to a solution, please?
The problem is that you haven't made any CCTest-instances.
So after you make the CCTest[] cls = new CCTest[5]; the five CCTest-objects are null. You should create them if they don't exist yet:
CCTest[] cls = new CCTest[5];
for (int i = 0; i < (Size = 5); i++) {
// We create a new CCTest-instance if it doesn't exist yet:
if(cls[i] == null){
cls[i] = new CCTest();
}
cls[i].x = new double[this.c][this.D][this.Size];
for (int j = 0; j < this.D; j++) {
cls[i].x = getRandomX(this.c, this.D, this.Size);
}
}
Alternatively, you could create them first, and then do the for-loop to assign the random doubles:
CCTest[] cls = new CCTest[5];
for (int i = 0; i < cls.length; i++) {
cls[i] = new CCTest();
}
for (int i = 0; i < (Size = 5); i++) {
cls[i].x = new double[this.c][this.D][this.Size];
for (int j = 0; j < this.D; j++) {
cls[i].x = getRandomX(this.c, this.D, this.Size);
}
}
I'm working on a project that will do a simple contrast of an image, I have already scanned through the arrays to find the min and max values but now I have to paint the image.
I keep getting this error "The operator * is undefined for the argument type(s) drawingpanel, double"
here is the code
public void simple (Graphics g) {
if (DrawingPanel.imageArray != null) {
int width = getWidth();
int height = getHeight();
int hPos = (width - DrawingPanel.imageArray[0].length) / 2;
int vPos = (height - DrawingPanel.imageArray.length) / 2;
for (int r = 0; r < DrawingPanel.imageArray.length; r++)
for (int c = 0; c < DrawingPanel.imageArray[r].length; c++) {
newc = Math.round(maxshade * ((double)(DrawingPanel.imageArray[r][c] - minshade) / (maxedshade - minshade))); //error here!!!
g.setColor(new Color(DrawingPanel.imageArray[r][c], DrawingPanel.imageArray[r][c], DrawingPanel.imageArray[r][c]));
g.drawLine(c+hPos, r+vPos, c+hPos, r+vPos);
}
g.setColor(Color.black);
g.drawRect(hPos, vPos, DrawingPanel.imageArray[0].length, DrawingPanel.imageArray.length);
}
}
Any help would be appreciated.. thanks!
also this is where i compute my min maxes...
public static void computeImageStatistics(DrawingPanel array) {
DrawingPanel.array = carray;
maxedshade = carray[0][0];
for (int i = 0; i < carray.length; i++) {
for (int j = 0; j < carray[i].length; j++) {
if (carray[i][j] > maxedshade) {
maxedshade = carray[i][j];
}
}
}
minshade = carray[0][0];
for (int i = 0; i < carray.length; i++) {
for (int j = 0; j < carray[i].length; j++) {
if (minshade > carray[i][j]) {
minshade = carray[i][j];
}
}
}
}
and some other variables in my DrawingPanel..
public void showImage(File fileName) {
Scanner scan;
try {
scan = new Scanner(fileName);
typefile = scan.next();
iname = scan.next();
width = scan.nextInt();
height = scan.nextInt();
maxshade = scan.nextInt();
array = new int[width][height];
for(int r = 0; r < array.length; r++)
for(int c = 0; c < array[r].length; c++)
array[r][c] = scan.nextInt();
imageArray = array;
repaint();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
The error msg tells you can not use the operator '*' between maxshade and ((double)(DrawingPanel.imageArray[r][c] - minshade) / (maxedshade - minshade)). Because maxshade is type of DrawingPanel , NOT a numeric(double/long/float/int...).
As I look into your 2nd code block,I see a static variable name maxedshade .It seems like a numeric.
And then I look into your error line:
newc = Math.round(maxshade * ((double)(DrawingPanel.imageArray[r][c] - minshade) / (maxedshade - minshade))); //error here!!!
Did you made a input mistake on "maxshade" ? Should it be maxedshade ?