*****************************************c++代码
MYDLL int GetCenterPos(uchar* imageData,int step, int widthValue, int heightValue, int BinaryThreshold, int LineBlankThreshold, int* centerX, int* centerY)
{
//Mat src(widthValue, heightValue, CV_8UC3);
//cvtColor(src, src, CV_RGB2GRAY);
//memcpy(imageData, src.data, sizeof(uchar)*src.rows*src.cols * 3);
Mat src = cv::Mat(heightValue, widthValue, CV_8UC4, imageData,step);//很重要的参数:CV_8UC4
/*return src.cols;*/
/*return src.rows;*/
/*imshow("图1", src);*/
/*return 99;*/
int ImageWidth = src.cols;
int ImageHeight = src.rows;
/*Mat src ImageWidth= imread(path);*/
// 结果图
Mat dst;
//灰度图转换
cvtColor(src, dst, COLOR_RGB2GRAY);
// 高斯模糊,主要用于降噪
GaussianBlur(dst, dst, Size(3, 3), 0);
// 二值化图,主要将灰色部分转成白色,使内容为黑色
threshold(dst, dst, BinaryThreshold, 255, THRESH_BINARY_INV);
// 中值滤波,同样用于降噪
medianBlur(dst, dst, 3);
//blur(dst, dst, Size(3, 3));//平滑处理
//***********获取中心算法
/*imshow("图2", dst);*/
//********************************************横向遍历
//map
vector
vector
int height = dst.rows;
int width = dst.cols;
for (int i = 0; i < height; i++) {
if (i % LineBlankThreshold == 0)
{
int num = 0;
vecMyHouse.clear();
for (int j = 0; j < width; j++) {
int index = i * width + j;
//像素值
int data = (int)dst.data[index];
if (data == 0)
{
/*mp.X = j;
mp.Y = i;*/
vecMyHouse.push_back(j);
}
}
//******
int tempX = 0;
int tempY = 0;
int count = vecMyHouse.size();
if (count > 50)
{
int a = 0;
}
if (vecMyHouse.size() <3)continue;
if (vecMyHouse.size() > 20)continue;
//sort(vecMyHouse.begin(), vecMyHouse.end());//大小排序
//最大值:
int max = *max_element(vecMyHouse.begin(), vecMyHouse.end());//过滤
int min = *min_element(vecMyHouse.begin(), vecMyHouse.end());//过滤
int tempCount = 0;
//利用keySet方法将map中键放入到Set中,可以使用 增强for
for (int k = 0; k < vecMyHouse.size(); k++) {
if (vecMyHouse[k] != max&&vecMyHouse[k] != min)
{
tempX += vecMyHouse[k];
tempCount++;
}
}
int value = (int)(tempX*1.0 / tempCount);
HorizonMyHouse.push_back(value);
num++;
}
}
int tempX = 0;
//最大值:
int max = *max_element(HorizonMyHouse.begin(), HorizonMyHouse.end());//过滤
//最小值:
int min = max;//*min_element(HorizonMyHouse.begin(), HorizonMyHouse.end());//过滤
sort(HorizonMyHouse.begin(), HorizonMyHouse.end());//大小排序
int count = HorizonMyHouse.size();
for (int z = 0; z < HorizonMyHouse.size(); z++)
{
if (min>HorizonMyHouse[z] && HorizonMyHouse[z] != 0)
{
min = HorizonMyHouse[z];
}
tempX += HorizonMyHouse[z];
}
tempX = tempX - (max + min);
if (HorizonMyHouse.size() > 2)
{
*centerX = (tempX *1.0 / (HorizonMyHouse.size() - 2));
}
else
{
*centerX = (HorizonMyHouse[0] + HorizonMyHouse[1]) / 2;
}
*centerX += 1;
#if 1
//********************************************纵向遍历
//map
vector
vector
height = dst.rows;
width = dst.cols;
for (int i = 0; i < width; i++) {
if (i % LineBlankThreshold == 0)
{
int num = 0;
vecMyHouse2.clear();
for (int j = 0; j < height; j++) {
int index = j * width + i;
//像素值
int data = (int)dst.data[index];
if (data == 0)
{
/* mp.X = i;
mp.Y = j;*/
vecMyHouse2.push_back(j);
}
}
//******
int tempX = 0;
int tempY = 0;
int count = vecMyHouse.size();
if (vecMyHouse2.size() <3)continue;
if (vecMyHouse2.size() > 20)continue;
sort(vecMyHouse2.begin(), vecMyHouse2.end());//大小排序
//最大值:
int max = *max_element(vecMyHouse2.begin(), vecMyHouse2.end());//过滤
int min = *min_element(vecMyHouse2.begin(), vecMyHouse2.end());//过滤
int tempCount = 0;
//利用keySet方法将map中键放入到Set中,可以使用 增强for
for (int k = 0; k < vecMyHouse2.size(); k++) {
if (vecMyHouse2[k] != max&&vecMyHouse2[k] != min)
{
tempX += vecMyHouse2[k];
tempCount++;
}
}
int value = (int)(tempX / tempCount);
verticalMyHouse.push_back(value);
num++;
}
}
int tempY = 0;
//最大值:
max = *max_element(verticalMyHouse.begin(), verticalMyHouse.end());//过滤
//最小值:
min = max; //*min_element(verticalMyHouse.begin(), verticalMyHouse.end());//过滤
for (int z = 0; z < verticalMyHouse.size(); z++)
{
if (min>verticalMyHouse[z] && verticalMyHouse[z] != 0)
{
min = verticalMyHouse[z];
}
tempY += verticalMyHouse[z];
}
tempY = tempY - (max + min);
if (verticalMyHouse.size()>2)
{
*centerY = tempY / (verticalMyHouse.size() - 2);
}
else
{
*centerY = (verticalMyHouse[0] + verticalMyHouse[1]) / 2;
}
*centerY += 1;
#endif
return 0;
}
**********************************C#代码
public class ImageDll
{
[DllImport(@"G:\whh\2020\projectTest\c++\ImageAnalysis\ImageAnalysisTest2020.1.3\ImageAnalysisTest\x64\Debug\CrossDiscern.dll", EntryPoint = "GetCenterPos", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetCenterPos(IntPtr imageData,int step, int widthValue, int heightValue, int BinaryThreshold, int LineBlankThreshold, ref int centerX, ref int centerY);
[DllImport(@"CrossDiscern.dll", EntryPoint = "Sum", CallingConvention = CallingConvention.Cdecl)]
public static extern int Sum(int a, int b);
//**********图片数据转换
public static int GetPositionResult_XY(Bitmap bitmap,int BinaryThreshold, int LineBlankThreshold, ref int centerX, ref int centerY)
{
#if false
BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
IntPtr pSt = bmpdata.Scan0;
int bytes = bitmap.Width * bitmap.Height * 3;
byte[] rgbValues = new byte[bytes];
Marshal.Copy(pSt, rgbValues, 0, bytes);
int res = GetCenterPos(rgbValues, bmpdata.Stride, bitmap.Width, bitmap.Height, BinaryThreshold, LineBlankThreshold, ref centerX, ref centerY);
bitmap.UnlockBits(bmpdata);
return res;
#endif
#if true
BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
IntPtr pSt = bmpdata.Scan0;
int bytes = bitmap.Width * bitmap.Height * 3;
byte[] rgbValues = new byte[bytes];
Marshal.Copy(pSt, rgbValues, 0, bytes);
int res = GetCenterPos(pSt, bmpdata.Stride, bitmap.Width, bitmap.Height, BinaryThreshold, LineBlankThreshold, ref centerX, ref centerY);
bitmap.UnlockBits(bmpdata);
return res;
#endif
}
}
c#调用
private void button_GetCenterPos_Click(object sender, EventArgs e)
{
Bitmap map = new Bitmap(sourceImage);
int x=0;
int y=0;
if( ImageDll.GetPositionResult_XY(map, 80, 20, ref x, ref y)==0)
{
//MessageBox.Show("识别成功!","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
string content = "";//"图像大小:" + "\r\n";
content += "起点:X=0 Y=0"+"\r\n";
content +=( "终点:X=" + map.Width.ToString()+" Y="+map.Height.ToString()+"\r\n");
content += "中线点:X=" + x.ToString() + " Y=" + y.ToString() + "\r\n";
label4.Text = content;
//*********绘制中心点
Graphics graphics = panel3.CreateGraphics();
Font font = new Font("宋体",16,FontStyle.Bold/*|FontStyle.Italic|FontStyle.Underline*/,GraphicsUnit.Point);//其中宋体是字体,24是字号,FontStyle的几个是字的样式,最后的GraphicsUnit是字的度量单位(可以看一下上边的表)
graphics.DrawString("识别成功!\r\n" + content, font, Brushes.Blue, new Point(panel3.Width / 2 - 72, 25));//绘制字体,font是上边定义的字体,Brushes.Brown是颜色,Point是字从哪个位置开始绘制
Brush b = new SolidBrush(Color.Red);//声明的画刷
int margin = 20;
int tempx = Convert.ToInt32(x * 1.0 / map.Width * (panel3.Width - 2 * margin) + margin);
int tempy = Convert.ToInt32(y * 1.0 / map.Height * (panel3.Height - 2 * margin) + margin);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;//平滑绘制
graphics.FillEllipse(b, new Rectangle(tempx-5,tempy-5, 10,10));
graphics.Dispose();
}
else
{
MessageBox.Show("识别失败!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}