I'm trying to convert my code which has SetPixel to SetPixels32. Below is my code with SetPixel
for (int x = 0; x < _brush.width; x++)
{
for (int y = 0; y < _brush.height; y++)
{
data = (pixelXOffset + x) + (pixelYOffset + y) * _templateDirtMask.width;
if (data > 0 && data < pixels.Length)
{
Color pixelDirt = _brush.GetPixel(x, y);
Color pixelDirtMask = _templateDirtMask.GetPixel(pixelXOffset + x, pixelYOffset + y);
pixels[data] = new Color(0, pixelDirtMask.g * pixelDirt.g, 0);
}
}
}
_templateDirtMask.SetPixels(pixels);
_templateDirtMask.Apply();
Then this is my code for SetPixels32
for (int x = 0; x < _brush.width; x++)
{
for (int y = 0; y < _brush.height; y++)
{
int arrElement = (pixelXOffset + x) + ((pixelYOffset + y) * heightScreenRes);
if (arrElement > 0 && arrElement < dirtMaskArr.Length)
{
Color32 pixelDirt = brushPixels[x + (y * 32)];
Color32 pixelDirtMask = dirtMaskArr[arrElement];
double pixelDirtMaskA = pixelDirtMask.g / 255.0;
double pixelDirtA = pixelDirt.g / 255.0;
double a = (pixelDirtMaskA * pixelDirtA) * 255;
dirtMaskArr[arrElement] = new Color32(0, Convert.ToByte(a), 0, 255);
}
}
}
_templateDirtMask.SetPixels32(dirtMaskArr);
_templateDirtMask.Apply(false);
My problem is it's not working.
Related
I'm trying to create a simple edge detection filter. And as I said it works with only one image. I'm trying to create this filter with 2 steps.
Blurring image (with meanfilter)
Calculate ( Original image-Blurring image)
The first step works well. And code of second one is simple like first one. But I see an error message:
System.ArgumentOutOfRangeException: 'Parameter must be positive and < Height.
Parameter name: y'
Working image:https://i.hizliresim.com/dLXkbn.png
My code:
public void edgedetectionfilter( )
{
Bitmap InputPicture,BlurredPicture, OutputPicture;
InputPicture = new Bitmap(pBox_SOURCE.Image);
BlurredPicture = new Bitmap(pBox_PROCESSED.Image);
int PicWidth = InputPicture.Width;
int PicHeight= InputPicture.Height;
OutputPicture = new Bitmap(PicWidth, PicHeight);
OutputPicture = InputPicture;
int x, y, difR, difG, difB;
Color OrgPicColoValue,BluredPicColorValue;
for (x = 0; x < PicWidth; x++)
{
for (y = 0; y < PicWidth; y++)
{
BluredPicColorValue = BlurredPicture.GetPixel(x, y);
OrgPicColoValue = InputPicture.GetPixel(x, y); //ERROR LINE
difR = Convert.ToInt16(OrgPicColoValue.R -BluredPicColorValue.R);
difG = Convert.ToInt16(OrgPicColoValue.G- BluredPicColorValue.G );
difB = Convert.ToInt16(OrgPicColoValue.B- BluredPicColorValue.B);
if (difR > 255) difR = 255;
if (difG > 255) difG = 255;
if (difB > 255) difB = 255;
if (difR < 0) difR = 0;
if (difG < 0) difG = 0;
if (difB < 0) difB = 0;
OutputPicture.SetPixel(x, y, Color.FromArgb(difR, difG, difB));
}
}
pBoxMedian.Image = OutputPicture;
}
public void meanfilter(int p)
//KERNELSIZE=P
{
if (sliderKernel.Value % 2 == 0)
{
MessageBox.Show("Enter an odd number");
return;
}
Color ColorValue;
Bitmap InputPicture, OutputPicture;
InputPicture = new Bitmap(pBox_SOURCE.Image);
int PicWidth = InputPicture.Width;
int PicHeight= InputPicture.Height;
OutputPicture = new Bitmap(PicWidth, PicHeight);
OutputPicture = InputPicture;
int x, y, i, j, sumR, sumG, sumB, avgR, avgG, avgB;
for (x = (KernelSize - 1) / 2; x < PicWidth - (KernelSize - 1) / 2; x++)
{
for (y = (KernelSize - 1) / 2; y < PicHeight - (KernelSize- 1) / 2; y++)
{
toplamR = 0;
toplamG = 0;
toplamB = 0;
for (i = -((KernelSize - 1) / 2); i <= (KernelSize - 1) / 2; i++)
{
for (j = -((KernelSize - 1) / 2); j <= (KernelSize - 1) / 2; j++)
{
ColorValue= InputPicture.GetPixel(x + i, y + j);
sumR = sumR + ColorValue.R;
sumG = sumG + ColorValue.G;
sumB = sumB + ColorValue.B;
}
}
avgR = sumR / (KernelSize * KernelSize );
avgG = sumG / (KernelSize *KernelSize );
avgB = sumB / (KernelSize * KernelSize );
OutputPicture.SetPixel(x, y, Color.FromArgb(avgR, avgG, avgB));
}
}
pBox_PROCESSED.Image = OutputPicture;
}
You compare y < PicWidth, whereas you probably want y < PicHeight. Is the image it worked on square, by chance?
This program works with Median filter. I need help with fixing the code. It applies to the line
if ((diffX > -1) && (diffY > -1)...
...in the MedianOfArea method. It would be better if the pixels, which are included in the loop's bounds, would be determined initially. This solution helps to avoid checking every time. Can you help me with fixing it?
namespace Recognizer
{
internal static class MedianFilterTask
{
public static double[,] MedianFilter(double[,] original)
{
var filter = new double[original.GetLength(0), original.GetLength(1)];
var lengthX = original.GetLength(0);
var lengthY = original.GetLength(1);
for (var x = 0; x < lengthX; x++)
for (var y = 0; y < lengthY; y++)
filter[x, y] = MedianOfArea(x, y, original, lengthX, lengthY);
return filter;
}
public static double MedianCount(ref double median, List<double> pixelsFields)
{
pixelsFields.Sort();
var countPixels = pixelsFields.Count;
if (countPixels % 2 == 0)
median = (pixelsFields[countPixels / 2 - 1] + pixelsFields[countPixels / 2]) / 2;
else
median = pixelsFields[countPixels / 2];
return median;
}
public static double MedianOfArea(int x, int y, double[,] original, int lengthX, int lengthY)
{
var pixelsFields = new List<double>();
double median = 0;
for (int areasX = -1; areasX < 2; areasX++)
for (int areasY = -1; areasY < 2; areasY++)
{
var diffX = x + areasX;
var diffY = y + areasY;
if ((diffX > -1) && (diffY > -1) && (diffX < lengthX) && (diffY < lengthY))
pixelsFields.Add(original[diffX, diffY]);
}
MedianCount(ref median, pixelsFields);
return median;
}
}
}
You could iterate directly on diffX (and diffY) and use Min and Max to set the ranges to loop over:
using System;
int startX = Math.Max(0, x-1);
int endX = Math.Min(lengthX, x+2);
int startY = Math.Max(0, y-1);
int endY = Math.Min(lengthY, y+2);
for (int diffX = startX; diffX < endX; diffX++)
for (int diffY = startY; diffY < endY; diffY++)
pixelsFields.Add(original[diffX, diffY]);
There is my Code, But drawing is very slow:
int BlockWidth = 16
SourceBlueMap = new Bitmap(BlocksRect.Width, BlocksRect.Height);
Graphics Gpi = Graphics.FromImage(SourceBlueMap);
AlphaBlock block;
string strPath = #"C:\Users\Administrator\Desktop\Blocks";
BlockInfo blockinfo;
for (int x = 0; x < iXDim; x++)
{
for (int y = 0; y < iYDim; y++)
{
for (int z = 0; z < iZDim; z++)
{
block = Blocks.GetBlock(x, y, z);
rect.X = x * BlockWidth;
rect.Y = z * BlockWidth;
if (BlockInfoList.Exists(info =>
info.ID == block.ID && info.Data == block.Data))
{
blockinfo = BlockInfoList.Find(info =>
info.ID == block.ID && info.Data == block.Data);
if (File.Exists(strPath + "\\" + blockinfo.Name + ".png"))
{
using (Bitmap bmp = new Bitmap(strPath + "\\" + blockinfo.Name + ".png"))
{
Gpi.DrawImage(bmp, rect);
}
}
}
}
}
}
Gpi.Dispose();
Draw a 256 * 256 size map takes 6 seconds.
But other programs use draw than 1 second:
http://www.diamondpants.com/spritecraft/PayPalDonate.aspx
I need to implement Harris corner detection, which should only have positive R values. If I use threshold of R>0, it highlights nothing, if R < 0 however, from even -0.00001 to -1000000 it outputs perfect edge detection, but no corners.
Input and output:
http://imgur.com/a/TtQSD\
Main Code:
Bitmap b = (Bitmap)pictureBox1.Image;
var i = IntensityMat(b);
var n = Mask(i,-0.00000001);
var ty = ToBit(n);
pictureBox1.Image = ty;
Functions:
public double Intensity(Color c)
{
int x = c.R;
int y = c.G;
int z = c.B;
return Math.Sqrt(x * x + y * y + z * z);
}
public double Trace(double[,] m)
{
double sum = 0;
for (int i = 0; i < m.GetLength(0); i++)
{
sum += m[i, i];
}
return sum;
}
public double[,] M(double ix,double iy)
{
double[,] m = new double[2, 2];
m[0, 0] = ix*ix;
m[1, 1] = iy*iy;
m[0, 1] = ix * iy;
m[1, 0] = ix * iy;
return m;
}
public double Det(double[,] m)
{
return m[1, 1] * m[0, 0] - m[0, 1] * m[1, 0];
}
public double R(double[,] m,double k=0.04)
{
var t = Trace(m);
return Det(m) - k * t * t;
}
int[,] IntensityMat(Bitmap b)
{
int[,] n = new int[b.Width, b.Height];
for (int i = 0; i < b.Width; i++)
{
for (int j = 0; j < b.Height; j++)
{
Color c = b.GetPixel(i, j);
n[i, j] = (int)Intensity(c);
}
}
return n;
}
Bitmap ToBit(int[,] bd)
{
Bitmap b = new Bitmap(bd.GetLength(0), bd.GetLength(1));
for (int i = 0; i < b.Width; i++)
{
for (int j = 0; j < b.Height; j++)
{
var t = bd[i, j];
b.SetPixel(i, j, Color.FromArgb(t, t, t));
}
}
return b;
}
int[,] Mask(int[,] m,double thresh)// m matrix of I
{
int[,] n = new int[m.GetLength(0), m.GetLength(1)];
for (int i = 1; i < m.GetLength(0); i++)
{
for (int j = 1; j < m.GetLength(1); j++)
{
double ix = Math.Abs(m[i-1,j]-m[i,j]);
double iy = Math.Abs(m[i , j-1] - m[i, j]);
var lap = M(ix, iy);
var r = R(lap);
if (r > thresh)
{
n[i, j] = 255;
}
}
}
return n;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to create a dungeon generator for a project I've been working on based off of this algorithm. I've gotten everything down, but my array (Fig. 1) doesn't seem to be holding giving the map data for some reason. I'm using three types of data to determine if a cell in the map is either empty (0), a space a character can be on (1), a hallway (2), or a wall (3).
I've gotten a bit stuck on this portion so any help is appreciated!
EDIT: The problem is the map object isn't storing the data in the loop shown in Fig. 1. Sorry for being so vague.
(Fig. 1)
for (int i = 0; i < roomList.Count; i++)
{
for (int x = roomList[i].X; x < (roomList[i].X + roomList[i].W); x++)
{
for (int y = roomList[i].Y; y < (roomList[i].Y + roomList[i].H); y++)
{
map[x, y] = 1;
}
}
}
(All of my relevant code)
namespace Project
{
}
public class Room
{
int xValue, yValue, widthValue, heightValue;
public int X
{
get { return xValue; }
set { xValue = value; }
}
public int Y
{
get { return yValue; }
set { yValue = value; }
}
public int W
{
get { return widthValue; }
set { widthValue = value; }
}
public int H
{
get { return heightValue; }
set { heightValue = value; }
}
}
public class DungeonGenerate
{
public int baseWidth = 513;
public int baseHeight = 513;
public int width = 64;
public int height = 64;
Color[,] arrayColor;
Random rand = new Random();
Room room = new Room();
Rectangle[,] rectMap;
public void Generate()
{
rectMap = new Rectangle[baseWidth, baseHeight];
//Creates a 2-D Array/Grid for the Dungeon
int[,] map = new int[baseWidth, baseHeight];
//Determines all the cells to be empty until otherwise stated
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
map[x, y] = 0;
}
}
//Determines the amount of rooms in the dungeon
int minRooms = (width * height) / 300;
int maxRooms = (width * height) / 150;
int amountOfRooms = rand.Next(minRooms, maxRooms);
//Room dimensions
int widthRoot = Convert.ToInt32(Math.Round(Math.Sqrt(width * 2)));
int heightRoot = Convert.ToInt32(Math.Round(Math.Sqrt(height * 2)));
int minWidth = Convert.ToInt32(Math.Round((width * .5) / widthRoot));
int maxWidth = Convert.ToInt32((width * 2) / widthRoot);
int minHeight = Convert.ToInt32(Math.Round(height * .5) / heightRoot);
int maxHeight = Convert.ToInt32((height * 2) / heightRoot);
//Creates the rooms
List<Room> roomList = new List<Room>(amountOfRooms);
for (int i = 0; i < amountOfRooms; i++)
{
bool ok = false;
do
{
room.X = rand.Next(width);
room.Y = rand.Next(height);
room.W = (rand.Next(maxWidth)) + minWidth;
room.H = (rand.Next(maxHeight)) + minHeight;
if (room.X + room.W >= width && room.Y + room.H >= height)
{
continue;
}
for (int q = 0; q < roomList.Count; q++)
{
if (room.X > roomList[q].X && room.X < roomList[q].X + room.W && room.Y > roomList[q].Y && room.Y < roomList[q].Y + room.H)
{
ok = false;
break;
}
}
ok = true;
roomList.Add(room);
} while (!ok);
}
//This will create hallways that lead to and from the rooms
int connectionCount = roomList.Count;
List<Point> connectedCells = new List<Point>((width * height));
for (int i = 0; i < connectionCount; i++)
{
Room roomA = roomList[i];
int roomNum = i;
while (roomNum == i)
{
roomNum = rand.Next(roomList.Count);
}
Room roomB = roomList[roomNum];
//Increasing this will make the hallway more straight, decreasing it will make the hallway more skewed
int sidestepChance = 10;
Point pointA = new Point(x: (rand.Next(roomA.W)) + roomA.X, y: (rand.Next(roomA.H)) + roomA.Y);
Point pointB = new Point(x: (rand.Next(roomB.W)) + roomB.X, y: (rand.Next(roomB.H)) + roomB.Y);
while (pointA != pointB)
{
int num = rand.Next() * 100;
if (num < sidestepChance)
{
if (pointB.X != pointA.X)
{
if (pointB.X > pointA.X)
{
pointB.X--;
}
else
{
pointB.X++;
}
}
}
else if(pointB.Y != pointA.Y)
{
if (pointB.Y > pointA.Y)
{
pointB.Y--;
}
else
{
pointB.Y++;
}
}
}
if (pointB.X < width && pointB.Y < height)
{
connectedCells.Add(pointB);
}
}
//Fills the room with data
for (int i = 0; i < roomList.Count; i++)
{
for (int x = roomList[i].X; x < (roomList[i].X + roomList[i].W); x++)
{
for (int y = roomList[i].Y; y < (roomList[i].Y + roomList[i].H); y++)
{
map[x, y] = 1;
}
}
}
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
if (map[x, y] == 0)
{
bool wall = false;
for (int yy = y - 2; yy < y + 2; yy++)
{
for (int xx = x - 2; xx < x + 2; xx++)
{
if (xx > 0 && yy > 0 && xx < width && yy < height)
{
if (map[xx, yy] == 1 || map[xx, yy] == 2)
{
map[x, y] = 3;
wall = true;
}
}
}
if (wall)
{
break;
}
}
}
}
}
//Rendering the Map and giving it some Color (Sort of)!
int scaler = baseWidth / width;
for (int x = 0; x < baseWidth; x++)
{
for (int y = 0; y < baseHeight; y++)
{
rectMap[x, y] = new Rectangle(x, y, 1, 1);
arrayColor = new Color[baseWidth, baseHeight];
switch (map[x, y])
{
case 0:
arrayColor[x, y] = new Color(0,0,0);
break;
case 1:
arrayColor[x, y] = new Color(0,0,0);
break;
case 2:
arrayColor[x, y] = new Color(0,0,0);
break;
case 3:
arrayColor[x, y] = new Color (0,0,0);
break;
}
}
}
}
public Rectangle[,] GetMap()
{
return rectMap;
}
public Color[,] GetColors()
{
return arrayColor;
}
}
In the for-loop where you're populating roomList, you're not instantiating a new Room each time. You're simply manipulating the same Room object and re-adding it to the list, so roomList will just contain many references to the same Room object. Try removing the room field from your DungeonGenerate class and use a local variable instead:
for (int i = 0; i < amountOfRooms; i++)
{
bool ok = false;
do
{
var room = new Room();
...
roomList.Add(room);
} while (!ok);
}