2024-07-18 09:50:08 +08:00
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "MicroImage.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using namespace cv;
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
MicroImage::MicroImage()
|
|
|
|
|
: m_width(0)
|
|
|
|
|
, m_height(0)
|
|
|
|
|
, m_OriginData(nullptr)
|
|
|
|
|
, m_CalData(nullptr)
|
|
|
|
|
, m_ImgName("")
|
|
|
|
|
, m_DistanceX(0.f)
|
|
|
|
|
, m_DistanceY(0.f)
|
|
|
|
|
, m_knowLength(0)
|
|
|
|
|
, m_TotalSize(0){
|
|
|
|
|
m_image.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MicroImage::~MicroImage() {
|
|
|
|
|
if(m_OriginData) delete m_OriginData;
|
|
|
|
|
if(m_CalData) delete m_CalData;
|
|
|
|
|
m_image.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string MicroImage::GetStrTime()
|
|
|
|
|
{
|
|
|
|
|
char buffer[50];
|
|
|
|
|
SYSTEMTIME snow;
|
|
|
|
|
GetLocalTime(&snow);
|
|
|
|
|
sprintf_s(buffer, sizeof(buffer), u8"%02d%02d%02d%02d%02d%03d", snow.wMonth, snow.wDay, snow.wHour, snow.wMinute, snow.wSecond, snow.wMilliseconds);
|
|
|
|
|
return string(buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MicroImage::Init(const BITMAP& bmp) {
|
|
|
|
|
m_height = bmp.bmHeight;
|
|
|
|
|
m_width = bmp.bmWidth;
|
|
|
|
|
m_Radio = m_width / m_height;
|
|
|
|
|
m_TotalSize = ((bmp.bmWidth * bmp.bmBitsPixel + 31) / 32) * 4 * bmp.bmHeight * bmp.bmPlanes;
|
|
|
|
|
m_OriginData = new uchar[m_TotalSize];
|
|
|
|
|
m_ImgName = u8"抓图" + GetStrTime();
|
|
|
|
|
memcpy_s(m_OriginData, m_TotalSize, bmp.bmBits, m_TotalSize);
|
|
|
|
|
|
|
|
|
|
//m_image = cv::Mat(m_height, m_width, CV_8UC3, m_OriginData);
|
|
|
|
|
//cv::imwrite(m_ImgName, m_image);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MicroImage::CropByBorder(int yBegin, int yEnd, int xBegin, int xEnd) {
|
|
|
|
|
for (int y = yBegin; y <= yEnd; ++y) {
|
|
|
|
|
for (int x = xBegin; x <= xEnd; ++x) {
|
|
|
|
|
auto& pc = m_image.at<Vec3b>(y, x);
|
|
|
|
|
if (pc[0] != 0 || pc[1] != 0 || pc[2] != 0) {
|
|
|
|
|
pc[0] = 0; pc[1] = 0; pc[2] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MicroImage::StatisticsBGColor() {
|
2024-07-18 18:17:33 +08:00
|
|
|
|
Rect cropRect1(m_width / 2 - 40, m_height / 2 - 40, 80, 80); // 中心位置
|
2024-07-18 09:50:08 +08:00
|
|
|
|
cropRect1 &= Rect(0, 0, m_width, m_height); // 检查ROI是否在图像范围内
|
|
|
|
|
Mat cropMat1 = m_image(cropRect1);
|
|
|
|
|
|
2024-07-18 18:17:33 +08:00
|
|
|
|
Rect cropRect2(0, m_height / 2 - 25, 50, 50); //中左位置
|
|
|
|
|
cropRect2 &= Rect(0, 0, m_width, m_height);
|
2024-07-18 09:50:08 +08:00
|
|
|
|
Mat cropMat2 = m_image(cropRect2);
|
|
|
|
|
|
2024-07-18 18:17:33 +08:00
|
|
|
|
Rect cropRect3(m_width - 25, m_height / 2 - 25, 50, 50); //中右位置
|
|
|
|
|
cropRect3 &= Rect(0, 0, m_width, m_height);
|
2024-07-18 09:50:08 +08:00
|
|
|
|
Mat cropMat3 = m_image(cropRect3);
|
|
|
|
|
|
2024-07-18 18:17:33 +08:00
|
|
|
|
Rect cropRect4(0, 0, 25, 25); //左上角位置
|
|
|
|
|
cropRect4 &= Rect(0, 0, m_width, m_height);
|
2024-07-18 09:50:08 +08:00
|
|
|
|
Mat cropMat4 = m_image(cropRect4);
|
|
|
|
|
|
|
|
|
|
StatisticsRGB(cropMat1);
|
|
|
|
|
StatisticsRGB(cropMat2);
|
|
|
|
|
StatisticsRGB(cropMat3);
|
|
|
|
|
StatisticsRGB(cropMat4);
|
|
|
|
|
|
|
|
|
|
printf("rgb size:%zd\n", m_RgbSet.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MicroImage::StatisticsRGB(cv::Mat& cropMat) {
|
|
|
|
|
for (int y = 0; y < cropMat.rows; ++y) {
|
|
|
|
|
for (int x = 0; x < cropMat.cols; ++x) {
|
|
|
|
|
Vec3b pixel = cropMat.at<Vec3b>(y, x);
|
|
|
|
|
int r = pixel[2]; // Red
|
|
|
|
|
int g = pixel[1]; // Green
|
|
|
|
|
int b = pixel[0]; // Blue
|
|
|
|
|
|
|
|
|
|
//RGB 每个值范围[-2,1],趋近0,偏黑
|
|
|
|
|
for (int i = -2; i <= 1; ++i) {
|
|
|
|
|
for (int j = -2; j <= 1; ++j) {
|
|
|
|
|
for (int k = -2; k <= 1; ++k) {
|
|
|
|
|
int rr = max(r + i, 0), gg = max(g + j, 0), bb = max(b + k, 0);
|
|
|
|
|
rr = min(r + i, 255), gg = min(g + j, 255), bb = min(b + k, 255);
|
|
|
|
|
m_RgbSet.insert((rr << 16) | (gg << 8) | (bb));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MicroImage::DrawRedLine(int length, int x, int y) {
|
|
|
|
|
int centerx = m_width / 2, centery = m_height / 2;
|
|
|
|
|
if (x == centerx) { //画水平线
|
|
|
|
|
for (int xx = centerx - length / 2; xx < centerx + length / 2; ++xx) { //设置红色
|
|
|
|
|
auto& pixel = m_image.at<Vec3b>(y, xx);
|
|
|
|
|
pixel[0] = 0;
|
|
|
|
|
pixel[1] = 0;
|
|
|
|
|
pixel[2] = 255;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else { //画垂直线
|
|
|
|
|
for (int yy = centery - length / 2; yy < centery + length / 2; ++yy) { //设置红色
|
|
|
|
|
auto& pixel = m_image.at<Vec3b>(yy, x);
|
|
|
|
|
pixel[0] = 0;
|
|
|
|
|
pixel[1] = 0;
|
|
|
|
|
pixel[2] = 255;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool MicroImage::IslandCheck(int y, int x, std::set<int>& tempSet) {
|
|
|
|
|
tempSet.insert((y << 16) | x);
|
|
|
|
|
queue<int> que;
|
|
|
|
|
que.push((y << 16) | x);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (!que.empty()) {
|
|
|
|
|
x = que.front() & 0xffff;
|
|
|
|
|
y = (que.front() >> 16) & 0xffff;
|
|
|
|
|
que.pop();
|
|
|
|
|
|
|
|
|
|
int val = (y << 16) + x + 1; //right
|
|
|
|
|
int colorVal = 0;
|
|
|
|
|
if (tempSet.find(val) == tempSet.end() && x + 1 < m_width) {
|
|
|
|
|
auto& right = m_image.at<Vec3b>(y, x + 1);
|
|
|
|
|
if (right[0] != 0 || right[1] != 0 || right[2] != 0) { //不是黑色判断
|
|
|
|
|
tempSet.insert(val);
|
|
|
|
|
que.push(val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = ((y + 1) << 16) + x; //down
|
|
|
|
|
if (tempSet.find(val) == tempSet.end() && y + 1 < m_height) {
|
|
|
|
|
auto& down = m_image.at<Vec3b>(y + 1, x);
|
|
|
|
|
if (down[0] != 0 || down[1] != 0 || down[2] != 0) { //不是黑色判断
|
|
|
|
|
tempSet.insert(val);
|
|
|
|
|
que.push(val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = (y << 16) + x - 1; //left
|
|
|
|
|
if (tempSet.find(val) == tempSet.end() && x - 1 >= 0) {
|
|
|
|
|
auto& left = m_image.at<Vec3b>(y, x - 1);
|
|
|
|
|
if (left[0] != 0 || left[1] != 0 || left[2] != 0) { //不是黑色判断
|
|
|
|
|
tempSet.insert(val);
|
|
|
|
|
que.push(val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = ((y - 1) << 16) | x; //up
|
|
|
|
|
if (tempSet.find(val) == tempSet.end() && y - 1 >= 0) {
|
|
|
|
|
auto& up = m_image.at<Vec3b>(y - 1, x);
|
|
|
|
|
if (up[0] != 0 || up[1] != 0 || up[2] != 0) { //不是黑色判断
|
|
|
|
|
tempSet.insert(val);
|
|
|
|
|
que.push(val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tempSet.size() > 400) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (que.empty()) //判断是孤岛噪点
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MicroImage::SquareRemove() {
|
|
|
|
|
for (int z = 50; z >= 5; z -= 5) { //步长
|
|
|
|
|
int x = 0;
|
|
|
|
|
int y = 0;
|
|
|
|
|
|
|
|
|
|
while (x < m_width && y < m_height) {
|
|
|
|
|
|
|
|
|
|
int allNum = 0, okNum = 0;
|
|
|
|
|
vector<Point> vec;
|
|
|
|
|
for (int i = y; i < m_height && i < y + z; ++i) { //计算边长z的方形,判断是否要变黑
|
|
|
|
|
for (int j = x; j < m_width && j < x + z; ++j) {
|
|
|
|
|
auto pc = m_image.at<Vec3b>(i, j);
|
|
|
|
|
int val = (pc[2] << 16) | (pc[1] << 8) | pc[0];
|
|
|
|
|
if ((pc[0] == 0 && pc[1] == 0 && pc[2] == 0) || m_RgbSet.find(val) != m_RgbSet.end()) { //判断是黑色或者背景色
|
|
|
|
|
++okNum;
|
|
|
|
|
}
|
|
|
|
|
++allNum;
|
|
|
|
|
vec.emplace_back(Point{ i,j });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (okNum * 1.0f / allNum >= 0.86f) { //背景像素占85%,全部置为黑色
|
|
|
|
|
for (auto& it : vec) {
|
|
|
|
|
auto& pc = m_image.at<Vec3b>(it.x, it.y);
|
|
|
|
|
pc[2] = 0;
|
|
|
|
|
pc[1] = 0;
|
|
|
|
|
pc[0] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (x + z < m_width) x += z;
|
|
|
|
|
else {
|
|
|
|
|
y += z; x = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//if (g_debug) {
|
|
|
|
|
// cv::imshow("result", m_image);
|
|
|
|
|
// cv::waitKey(0);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MicroImage::IsBlack(int y, int x) {
|
|
|
|
|
if (x < 0 || x >= m_width || y < 0 || y >= m_height) return true;
|
|
|
|
|
auto pc = m_image.at<Vec3b>(y, x);
|
|
|
|
|
if ((pc[0] != 0 || pc[1] != 0 || pc[2] != 0)) { //非黑色
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MicroImage::IsLandRemove() {
|
|
|
|
|
set<int> tempSet;
|
|
|
|
|
set<int> candiSet; //可能是孤岛噪点的位置
|
|
|
|
|
for (int y = 0; y < m_height; ++y) {
|
|
|
|
|
|
|
|
|
|
candiSet.clear();
|
|
|
|
|
int preLastBlack = -1;
|
|
|
|
|
for (int x = 0; x <= m_width; ++x) {
|
|
|
|
|
if (IsBlack(y, x) && !IsBlack(y, x - 1) && x - 1 - preLastBlack <= 40) {
|
|
|
|
|
candiSet.insert(x);
|
|
|
|
|
}
|
|
|
|
|
if (!IsBlack(y, x) && IsBlack(y, x - 1)) {
|
|
|
|
|
preLastBlack = x - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto x = candiSet.begin(); x != candiSet.end(); ++x) {
|
|
|
|
|
tempSet.clear();
|
|
|
|
|
if (IslandCheck(y, *x, tempSet)) { //是孤岛噪点
|
|
|
|
|
for (auto start = tempSet.begin(); start != tempSet.end(); ++start) {
|
|
|
|
|
Vec3b& pixel = m_image.at<Vec3b>(((*start) >> 16) & 0xffff, (*start) & 0xffff);
|
|
|
|
|
pixel[2] = 0;
|
|
|
|
|
pixel[1] = 0;
|
|
|
|
|
pixel[0] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//if (g_debug) {
|
|
|
|
|
// cv::imshow("result", m_image);
|
|
|
|
|
// cv::waitKey(0);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MicroImage::CalBorderCrop(int& dx, int& dy) {
|
|
|
|
|
//中心点发出一条线,向边缘平推
|
|
|
|
|
int centerx = m_width / 2, centery = m_height / 2;
|
|
|
|
|
int bNum = 0;
|
|
|
|
|
int lineLen = 250;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int j = centery;
|
|
|
|
|
int upDown = 0, upUp = 0;
|
|
|
|
|
while (j >= 0) {
|
|
|
|
|
bNum = 0;
|
|
|
|
|
for (int i = centerx - lineLen / 2; i < centerx + lineLen / 2; ++i) {
|
|
|
|
|
auto pixel = m_image.at<Vec3b>(j, i);
|
|
|
|
|
if (pixel[0] == 0 && pixel[1] == 0 && pixel[2] == 0) { //判断是黑色
|
|
|
|
|
++bNum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bNum * 1.f / lineLen <= 0.3f) { //算边界
|
|
|
|
|
if (upDown == 0) upDown = j; //矩形的下边
|
|
|
|
|
else {
|
|
|
|
|
upUp = j; //矩形的上边
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (upDown && upUp && bNum * 1.f >= lineLen * 0.95f) break;
|
|
|
|
|
}
|
|
|
|
|
if (bNum == lineLen) j -= 3;
|
|
|
|
|
else --j;
|
|
|
|
|
}
|
|
|
|
|
DrawRedLine(lineLen, centerx, upDown);
|
|
|
|
|
DrawRedLine(lineLen, centerx, upUp);
|
|
|
|
|
printf("upDown:%d,upUp:%d\n", upDown, upUp);
|
|
|
|
|
|
|
|
|
|
j = centery;
|
|
|
|
|
int downDown = 0, downUp = 0;
|
|
|
|
|
while (j < m_height) {
|
|
|
|
|
bNum = 0;
|
|
|
|
|
for (int i = centerx - lineLen / 2; i < centerx + lineLen / 2; ++i) {
|
|
|
|
|
auto pixel = m_image.at<Vec3b>(j, i);
|
|
|
|
|
if (pixel[0] == 0 && pixel[1] == 0 && pixel[2] == 0) { //判断是黑色
|
|
|
|
|
++bNum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bNum * 1.f / lineLen <= 0.3f) { //算边界
|
|
|
|
|
if (downUp == 0) downUp = j; //矩形的下边
|
|
|
|
|
else {
|
|
|
|
|
downDown = j; //矩形的上边
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (downDown && downUp && bNum * 1.f >= lineLen * 0.95f) break;
|
|
|
|
|
}
|
|
|
|
|
if (bNum == lineLen) j += 3;
|
|
|
|
|
else ++j;
|
|
|
|
|
}
|
|
|
|
|
DrawRedLine(lineLen, centerx, downDown);
|
|
|
|
|
DrawRedLine(lineLen, centerx, downUp);
|
|
|
|
|
printf("downDown:%d,downUp:%d\n", downDown, downUp);
|
|
|
|
|
|
|
|
|
|
int i = centerx;
|
|
|
|
|
int leftLeft = 0, leftRight = 0;
|
|
|
|
|
while (i >= 0) {
|
|
|
|
|
bNum = 0;
|
|
|
|
|
for (int y = centery - lineLen / 2; y < centery + lineLen / 2; ++y) {
|
|
|
|
|
auto pixel = m_image.at<Vec3b>(y, i);
|
|
|
|
|
if (pixel[0] == 0 && pixel[1] == 0 && pixel[2] == 0) { //判断是黑色
|
|
|
|
|
++bNum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bNum * 1.f / lineLen <= 0.3f) { //算边界
|
|
|
|
|
if (leftRight == 0) leftRight = i; //矩形的下边
|
|
|
|
|
else {
|
|
|
|
|
leftLeft = i; //矩形的上边
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (leftRight && leftLeft && bNum * 1.f >= lineLen * 0.95f) break;
|
|
|
|
|
}
|
|
|
|
|
if (bNum == lineLen) i -= 3;
|
|
|
|
|
else --i;
|
|
|
|
|
}
|
|
|
|
|
DrawRedLine(lineLen, leftRight, centery);
|
|
|
|
|
DrawRedLine(lineLen, leftLeft, centery);
|
|
|
|
|
printf("leftLeft:%d,leftRight:%d\n", leftLeft, leftRight);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i = centerx;
|
|
|
|
|
int rightLeft = 0, rightRight = 0;
|
|
|
|
|
while (i < m_width) {
|
|
|
|
|
bNum = 0;
|
|
|
|
|
for (int y = centery - lineLen / 2; y < centery + lineLen / 2; ++y) {
|
|
|
|
|
auto pixel = m_image.at<Vec3b>(y, i);
|
|
|
|
|
if (pixel[0] == 0 && pixel[1] == 0 && pixel[2] == 0) { //判断是黑色
|
|
|
|
|
++bNum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bNum * 1.f / lineLen <= 0.3f) { //算边界
|
|
|
|
|
if (rightLeft == 0) rightLeft = i; //矩形的下边
|
|
|
|
|
else {
|
|
|
|
|
rightRight = i; //矩形的上边
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (rightLeft && rightRight && bNum * 1.f >= lineLen * 0.95f) break;
|
|
|
|
|
}
|
|
|
|
|
if (bNum == lineLen) i += 3;
|
|
|
|
|
else ++i;
|
|
|
|
|
}
|
|
|
|
|
DrawRedLine(lineLen, rightLeft, centery);
|
|
|
|
|
DrawRedLine(lineLen, rightRight, centery);
|
|
|
|
|
printf("rightLeft:%d,rightRight:%d\n", rightLeft, rightRight);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CropByBorder(upDown + 1, downUp - 1, 0, leftLeft - 1);
|
|
|
|
|
CropByBorder(upDown + 1, downUp - 1, leftRight + 1, rightLeft - 1);
|
|
|
|
|
CropByBorder(upDown + 1, downUp - 1, rightRight + 1, m_width - 1);
|
|
|
|
|
|
|
|
|
|
CropByBorder(0, upUp - 1, 0, leftLeft - 1);
|
|
|
|
|
CropByBorder(0, upUp - 1, leftRight + 1, rightLeft - 1);
|
|
|
|
|
CropByBorder(0, upUp - 1, rightRight + 1, m_width - 1);
|
|
|
|
|
|
|
|
|
|
CropByBorder(downDown + 1, m_height - 1, 0, leftLeft - 1);
|
|
|
|
|
CropByBorder(downDown + 1, m_height - 1, leftRight + 1, rightLeft - 1);
|
|
|
|
|
CropByBorder(downDown + 1, m_height - 1, rightRight + 1, m_width - 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//if (g_debug) {
|
|
|
|
|
// cv::imshow("result", m_image);
|
|
|
|
|
// cv::waitKey(0);
|
|
|
|
|
//}
|
|
|
|
|
//cv::imwrite("11.png", m_image);
|
|
|
|
|
|
|
|
|
|
dy = downUp - upUp;
|
|
|
|
|
dx = rightLeft - leftLeft;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void MicroImage::CalDistance() {
|
|
|
|
|
m_image.release();
|
|
|
|
|
m_image = cv::Mat(m_height, m_width, CV_8UC3, m_OriginData).clone();
|
|
|
|
|
//cv::imwrite(m_ImgName, m_image);
|
2024-07-18 18:17:33 +08:00
|
|
|
|
//StandardLineDetect(); //标准线段检测 先固定值
|
2024-07-18 09:50:08 +08:00
|
|
|
|
StatisticsBGColor();
|
|
|
|
|
SquareRemove();
|
2024-07-18 18:17:33 +08:00
|
|
|
|
|
|
|
|
|
//#if 0
|
|
|
|
|
// IsLandRemove();
|
|
|
|
|
// Binarization();
|
|
|
|
|
//
|
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
|
|
|
2024-07-18 09:50:08 +08:00
|
|
|
|
int dx = 0, dy = 0;
|
|
|
|
|
CalBorderCrop(dx, dy);
|
2024-07-18 18:17:33 +08:00
|
|
|
|
m_knowLength = 148; //先固定
|
2024-07-18 09:50:08 +08:00
|
|
|
|
m_DistanceY = 0.2 * dy / m_knowLength;
|
|
|
|
|
m_DistanceX = 0.2 * dx / m_knowLength;
|
|
|
|
|
|
|
|
|
|
m_CalData = new uchar[m_TotalSize]{0};
|
|
|
|
|
memcpy_s(m_CalData, m_TotalSize,m_image.data,m_TotalSize);
|
|
|
|
|
m_image.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MicroImage::StandardLineDetect() {
|
|
|
|
|
int cropH = 250; //裁剪高
|
|
|
|
|
int cropW = 300; //裁剪宽
|
|
|
|
|
Rect cropRect(0, m_height - cropH, cropW, cropH); // 定义感兴趣的区域的矩形框
|
|
|
|
|
cropRect &= Rect(0, 0, m_width, m_height); // 检查ROI是否在图像范围内
|
|
|
|
|
Mat cropMat = m_image(cropRect);
|
|
|
|
|
|
|
|
|
|
//if (g_isDebug) {
|
|
|
|
|
// imshow("Mask", cropMat);
|
|
|
|
|
// cv::waitKey(0);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
cv::Mat m_HsvMat;
|
|
|
|
|
cv::cvtColor(cropMat, m_HsvMat, COLOR_BGR2HSV);
|
|
|
|
|
|
|
|
|
|
// 定义黑色的HSV范围
|
|
|
|
|
Scalar lower_black = Scalar(0, 0, 0);
|
|
|
|
|
Scalar upper_black = Scalar(180, 255, 60); // 对于V的区域进行了确定
|
|
|
|
|
|
|
|
|
|
Mat mask;
|
|
|
|
|
inRange(m_HsvMat, lower_black, upper_black, mask);
|
|
|
|
|
|
|
|
|
|
//if (g_isDebug) {
|
|
|
|
|
// cv::imshow("Mask", mask);
|
|
|
|
|
// cv::waitKey(0);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
int whiteThreshold = 250; //定义白色的灰度阈值 根据需要调整阈值
|
|
|
|
|
int width = mask.cols, height = mask.rows;
|
|
|
|
|
int whiteW = 0;
|
|
|
|
|
for (int y = 0; y < height; ++y) { //先行后列
|
|
|
|
|
int whiteCount = 0;
|
|
|
|
|
for (int x = 0; x < width; ++x) {
|
|
|
|
|
if (x > 0 && mask.at<uchar>(y, x) >= whiteThreshold && mask.at<uchar>(y, x - 1) >= whiteThreshold) { // 判断是否是白色像素
|
|
|
|
|
++whiteCount; // 这里可以根据需求处理白色像素,例如计数、修改像素值等
|
|
|
|
|
}
|
|
|
|
|
else whiteCount = 0;
|
|
|
|
|
whiteW = max(whiteCount + 1, whiteW); //要加上第一个像素点
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 遍历图像的每个像素
|
|
|
|
|
int whiteH = 0;
|
|
|
|
|
for (int x = 0; x < width; ++x) {
|
|
|
|
|
int whiteCount = 0;
|
|
|
|
|
for (int y = 0; y < height; ++y) {
|
|
|
|
|
if (y > 0 && mask.at<uchar>(y, x) >= whiteThreshold && mask.at<uchar>(y - 1, x) >= whiteThreshold) { // 判断是否是白色像素
|
|
|
|
|
++whiteCount; // 这里可以根据需求处理白色像素,例如计数、修改像素值等
|
|
|
|
|
}
|
|
|
|
|
else whiteCount = 0;
|
|
|
|
|
whiteH = max(whiteCount + 1, whiteH);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
printf("whiteW:%d,whiteH:%d\n", whiteW, whiteH);
|
|
|
|
|
|
|
|
|
|
m_knowLength = (int)(whiteW + whiteH) / 2;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|