我有一個影像,每個角包含四個圓圈,其中一個圓圈存在缺陷,那么如何識別它。我有很多帶有大小缺陷的影像。我正在調整影像的大小,因為影像的大小1920*1080是 size 960*540。我嘗試對影像進行歸一化,然后應用閾值和精明邊緣,但我不知道如何識別或識別影像。我正在使用 OpenCV C ,我是初學者,所以我不知道要應用哪種演算法。
我的影像是:并且您可以清楚地看到缺陷存在于左上角的圓圈中,而所有其他圓圈都沒有缺陷。

經過精明我的形象是這樣的:

到目前為止,我已經嘗試了以下代碼:
//resize image
Mat r_img;
resize(img, r_img, Size(img.cols / 2, img.rows / 2), 0, 0, INTER_LANCZOS4);
Mat gfilter;
cv::GaussianBlur(r_img, gfilter, Size(5, 5),2, 2);
//convert to grayscale
Mat gray_img;
cv::cvtColor(gfilter, gray_img, COLOR_BGR2GRAY);
double min, max;
cv::minMaxLoc(gray_img, &min, &max);
float sub = min;
float mult = 255.0f / (float)(max - sub);
cv::Mat normalized = gray_img - sub;
normalized = mult * normalized;
cv::imshow("normalized", normalized);
cv::Mat mask;
cv::threshold(normalized, mask, 127, 255, THRESH_BINARY)
Mat canny;
cv::Canny(normalized, canny, 50, 150, 3);
uj5u.com熱心網友回復:
為什么要采用調整大小和模糊等流程?我認為它們的作業方向是掩蓋缺陷。
我認為,將四個區域中的每一個都剪掉并 logPolar() 將幫助您找到缺陷。
這是使用 warpPolar() 的簡單示例。
//Circle Area Image.
// In this sample code, this image is created at here.
// In real, you must cut out the circle region from your source image.
cv::Mat TheSrcCircleImg = cv::Mat::zeros( 101, 101, CV_8UC3 );
cv::Point Center{ 50,50 }; //also, you must estimate this point.
{
//Draw some cielces
cv::circle( TheSrcCircleImg, Center, 48, cv::Scalar(8,96,16), -1 );
cv::circle( TheSrcCircleImg, Center, 35, cv::Scalar(0,128,0), -1 );
cv::circle( TheSrcCircleImg, Center, 22, cv::Scalar(255,32,0), 6 );
cv::circle( TheSrcCircleImg, Center, 29, cv::Scalar(100,100,100), 1 );
cv::circle( TheSrcCircleImg, Center, 10, cv::Scalar(0,0,0), -1 );
//Add "defects"
cv::line( TheSrcCircleImg, cv::Point(70,65), cv::Point(96,55), cv::Scalar(0,255,255), 2 );
cv::line( TheSrcCircleImg, cv::Point(45,32), cv::Point(30,30), cv::Scalar(0,255,255), 1 );
}
cv::imshow( "The Src", TheSrcCircleImg );
//I found that arguments of logPolar() is not explained in reference manual.
//So, I used werpPolar() intstead.
cv::Mat ResultImg;
cv::warpPolar( TheSrcCircleImg, ResultImg, cv::Size(50,360), Center, 50, cv::INTER_LINEAR cv::WARP_POLAR_LINEAR );
cv::imshow( "Result", ResultImg );
cv::waitKey();
社區機器人說“不清楚”,所以我試著把這個故事寫成代碼。結果,此代碼的結果似乎很差。有必要考慮檢測部分。
std::vector< std::vector< cv::Point> > FindOutlines( const cv::Mat &SrcImg8U1C )
{
cv::Mat BinImg;
cv::threshold( SrcImg8U1C, BinImg, 16, 255, cv::THRESH_BINARY );
std::vector< std::vector< cv::Point> > Contours;
cv::findContours( BinImg, Contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE );
return Contours;
}
//Test Process for 1 Circle Region
void Proc( const cv::Mat &SrcImg8U1C, const std::vector<cv::Point> &Outline, const std::string &ShowWndName )
{
cv::RotatedRect FittingResult = cv::fitEllipse( Outline );
cv::Rect Region = cv::boundingRect( Outline );
FittingResult.center.x -= Region.x;
FittingResult.center.y -= Region.y;
cv::Mat RegionImg;
cv::Mat ShowImg;
{
cv::equalizeHist( SrcImg8U1C(Region), RegionImg );
cv::cvtColor( RegionImg, ShowImg, cv::COLOR_GRAY2BGR );
ShowImg *= 0.5;
cv::ellipse( ShowImg, FittingResult, cv::Scalar(0,0,255) );
cv::drawMarker( ShowImg, FittingResult.center, cv::Scalar(0,255,0), cv::MARKER_CROSS, 8 );
}
const double radius = (FittingResult.size.width FittingResult.size.height) * 0.25;
cv::Mat LPImg;
cv::warpPolar( RegionImg, LPImg, cv::Size(cvRound(radius),180), FittingResult.center, radius, cv::INTER_LINEAR cv::WARP_POLAR_LINEAR );
cv::Mat DetectionMask = cv::Mat::zeros( LPImg.size(), CV_8U );
{//Detection based on edge direction. (looks Poor)
cv::Mat SobelX, SobelY;
cv::Sobel( LPImg, SobelX, CV_32F, 1,0 );
cv::Sobel( LPImg, SobelY, CV_32F, 0,1 );
const float SqMagThresh = 200 * 200;
const float DetectionRateThresh = 0.5f;
for( int y=0; y<LPImg.rows; y )
{
const float *pSX = SobelX.ptr<float>(y);
const float *pSY = SobelY.ptr<float>(y);
unsigned char *pD = DetectionMask.ptr<unsigned char>(y);
for( int x=0; x<LPImg.cols; x, pSX, pSY, pD )
{
if( (*pSX * *pSX) (*pSY * *pSY) < SqMagThresh )continue;
if( fabs(*pSY) >= fabs(*pSX)*DetectionRateThresh ){ *pD = 255; }
}
}
cv::Mat Morph;
cv::morphologyEx( DetectionMask, Morph, cv::MORPH_CLOSE, cv::Mat() );
cv::morphologyEx( Morph, Morph, cv::MORPH_OPEN, cv::Mat() );
cv::bitwise_and( Morph, DetectionMask, DetectionMask );
}
{//Draw Result : This inverse warp calculation is from Reference Manual.
const double Kangle = DetectionMask.rows / CV_2PI;
for( int y=0; y<DetectionMask.rows; y )
{
const double angleRad = y / Kangle;
const double Cos = cos(angleRad);
const double Sin = sin(angleRad);
const unsigned char *pD = DetectionMask.ptr<unsigned char>(y);
for( int x=0;x<DetectionMask.cols; x, pD )
{
if( !(*pD) )continue;
double Klin = DetectionMask.cols / radius;
double magnitude = x / Klin;
int x_reg = cvRound( FittingResult.center.x magnitude*Cos );
int y_reg = cvRound( FittingResult.center.y magnitude*Sin );
ShowImg.at<cv::Vec3b>(y_reg,x_reg) = cv::Vec3b(0,255,255);
}
}
}
cv::imshow( ShowWndName, ShowImg );
}
int main()
{
//The Image "ciecles.png" is copied from this Question.
cv::Mat SrcImg = cv::imread( "circles.png", cv::IMREAD_GRAYSCALE );
if( SrcImg.empty() )return 0;
std::vector< std::vector< cv::Point> > Outlines = FindOutlines( SrcImg );
for( size_t i=0; i<Outlines.size(); i ){ Proc( SrcImg, Outlines[i], std::string("Result") char('0' i) ); }
cv::waitKey();
return 0;
}
uj5u.com熱心網友回復:
準確定位圓心(很容易找到孔的輪廓);
展開影像以拉直環;
在小視窗上使用模板匹配來檢測與干凈部分的偏差。或者,只是影像差異。
評論:
拉直超過 360°,以確保模板在任何地方都嘗試過;
為了獲得模板,一個好的方法是對展開影像的所有輪廓進行平均,然后重復它以獲得方形影像。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/462343.html
上一篇:在棋盤OpenCV中檢測方塊
下一篇:有沒有辦法從影像中獲取所有資料?
